wordpress鏈接亞馬遜在線優(yōu)化工具
目錄
一、透視變換
1、什么是透視變換
2、操作步驟
? ? ? ? 1)選擇透視變換的源圖像和目標(biāo)圖像
? ? ? ? 2)確定透視變換所需的關(guān)鍵點(diǎn)
? ? ? ? 3)計(jì)算透視變換的變換矩陣
? ? ? ? 4)對(duì)源圖像進(jìn)行透視變換
? ? ? ? 5)對(duì)變換后的圖像進(jìn)行插值處理
二、輪廓檢測(cè)
1、什么是輪廓檢測(cè)
2、操作步驟
? ? ? ? 1)圖像預(yù)處理
? ? ? ? 2)邊緣檢測(cè)
? ? ? ? 3)邊緣連接
? ? ? ? 4)輪廓篩選
? ? ? ? 5)輪廓繪制
三、項(xiàng)目實(shí)施
1、定義展示圖片函數(shù)
2、定義自動(dòng)縮放圖片大小函數(shù)
3、定義輪廓點(diǎn)的排序函數(shù)
4、定義透視變換函數(shù)
5、讀取原圖并縮放
????????運(yùn)行結(jié)果:
6、進(jìn)行輪廓檢測(cè)
????????運(yùn)行結(jié)果:
5、繪制最大輪廓
????????運(yùn)行結(jié)果:
6、對(duì)最大輪廓進(jìn)行透視變換
????????運(yùn)行結(jié)果:
7、旋轉(zhuǎn)、二值化處理
????????運(yùn)行結(jié)果:
一、透視變換
1、什么是透視變換
????????透視變換是一種圖像處理技術(shù),用于將二維平面上的圖像或物體映射到三維空間中。它通過(guò)改變圖像的視角和投影來(lái)創(chuàng)建一個(gè)具有透視效果的圖像。
????????透視變換通常用于計(jì)算機(jī)圖像形態(tài)學(xué)和計(jì)算機(jī)視覺(jué)領(lǐng)域,用于實(shí)現(xiàn)圖像的透視效果、立體視覺(jué)、圖像校正等應(yīng)用。它可以模擬人眼在觀察遠(yuǎn)景時(shí)的透視效果,使得遠(yuǎn)處的物體看起來(lái)比近處的物體小,同時(shí)使得平行線在遠(yuǎn)處會(huì)相交的視覺(jué)效果。
????????透視變換的實(shí)現(xiàn)通常需要通過(guò)計(jì)算圖像中各點(diǎn)在三維空間中的坐標(biāo),并將其映射回二維平面上,從而實(shí)現(xiàn)透視效果。這個(gè)過(guò)程涉及到幾何變換、矩陣運(yùn)算和投影變換等數(shù)學(xué)概念和算法。
2、操作步驟
? ? ? ? 1)選擇透視變換的源圖像和目標(biāo)圖像
????????????????源圖像是需要進(jìn)行透視變換的原始圖像,目標(biāo)圖像是希望得到的透視變換后的圖像。
? ? ? ? 2)確定透視變換所需的關(guān)鍵點(diǎn)
????????????????根據(jù)透視變換的要求,需要選擇源圖像中的四個(gè)關(guān)鍵點(diǎn)以及對(duì)應(yīng)的目標(biāo)圖像中的四個(gè)關(guān)鍵點(diǎn)。這四個(gè)關(guān)鍵點(diǎn)共同決定了透視變換的變換矩陣。
? ? ? ? 3)計(jì)算透視變換的變換矩陣
????????????????通過(guò)四個(gè)關(guān)鍵點(diǎn)的對(duì)應(yīng)關(guān)系,使用透視變換的數(shù)學(xué)公式計(jì)算出透視變換的變換矩陣。這個(gè)變換矩陣將源圖像中的像素映射到目標(biāo)圖像中的像素。
? ? ? ? 4)對(duì)源圖像進(jìn)行透視變換
????????????????使用計(jì)算得到的變換矩陣,對(duì)源圖像中的每個(gè)像素進(jìn)行變換,計(jì)算其在目標(biāo)圖像中的對(duì)應(yīng)像素位置。
? ? ? ? 5)對(duì)變換后的圖像進(jìn)行插值處理
????????????????由于透視變換可能會(huì)導(dǎo)致源圖像中的像素映射到目標(biāo)圖像中的非整數(shù)位置,因此需要對(duì)其進(jìn)行插值處理,以得到最終的目標(biāo)圖像。
二、輪廓檢測(cè)
1、什么是輪廓檢測(cè)
????????輪廓檢測(cè)是一種圖像處理技術(shù),用于在圖像中找到物體的邊界。在圖像處理領(lǐng)域中,物體的邊界通常被表示為連續(xù)的曲線,這些曲線被稱為輪廓。輪廓檢測(cè)算法可以識(shí)別圖像中的明顯變化或不連續(xù)的像素,從而確定物體的形狀和結(jié)構(gòu)。
????????輪廓檢測(cè)算法的基本原理是通過(guò)分析圖像中的亮度、顏色或紋理等特征,找到物體與背景之間的顯著邊緣或變化。常用的輪廓檢測(cè)算法包括Canny邊緣檢測(cè)、Sobel算子、拉普拉斯算子等。
????????通過(guò)輪廓檢測(cè),可以實(shí)現(xiàn)圖像分割、目標(biāo)識(shí)別、形狀匹配等應(yīng)用。在計(jì)算機(jī)視覺(jué)和圖像處理領(lǐng)域中,輪廓檢測(cè)是一項(xiàng)重要的技術(shù),廣泛應(yīng)用于物體檢測(cè)與跟蹤、圖像分析與理解、機(jī)器視覺(jué)等領(lǐng)域。
2、操作步驟
? ? ? ? 1)圖像預(yù)處理
????????????????首先對(duì)輸入圖像進(jìn)行預(yù)處理,可以包括灰度化、平滑濾波、邊緣增強(qiáng)等操作,以減少噪聲和突出邊緣信息。
? ? ? ? 2)邊緣檢測(cè)
????????????????使用邊緣檢測(cè)算法(如Canny、Sobel、拉普拉斯等)來(lái)檢測(cè)圖像中的邊緣。這些算法通過(guò)計(jì)算像素間的梯度或差異,找到亮度或顏色變化較大的區(qū)域。
? ? ? ? 3)邊緣連接
????????????????將離散的邊緣點(diǎn)連接成連續(xù)的輪廓線。常用的方法包括利用邊緣點(diǎn)的鄰域信息進(jìn)行連接,或者利用輪廓線的閉合性質(zhì)進(jìn)行曲線追蹤。
? ? ? ? 4)輪廓篩選
????????????????根據(jù)一定的準(zhǔn)則對(duì)檢測(cè)到的輪廓進(jìn)行篩選,去除無(wú)關(guān)的輪廓??梢愿鶕?jù)輪廓的長(zhǎng)度、面積、形狀等特征進(jìn)行篩選。
? ? ? ? 5)輪廓繪制
????????????????最后,將篩選后的輪廓繪制在原始圖像上,以便觀察和分析。
具體可參考博客:
《深度學(xué)習(xí)》OpenCV 圖像輪廓檢測(cè)、輪廓處理及代碼演示https://ahao1004.blog.csdn.net/article/details/141830045?fromshare=blogdetail&sharetype=blogdetail&sharerId=141830045&sharerefer=PC&sharesource=qq_64603703&sharefrom=from_link
三、項(xiàng)目實(shí)施
1、定義展示圖片函數(shù)
import numpy as np
import cv2
def cv_show(name,img):cv2.imshow(name,img)cv2.waitKey(0)
2、定義自動(dòng)縮放圖片大小函數(shù)
# 調(diào)整圖像高寬,保持圖像寬高比不變
def resize(image,width=None,height=None ,inter=cv2.INTER_AREA): # 輸入?yún)?shù)為圖像、可選寬度、可選高度、插值方式默認(rèn)為cv2.INTER_AREA,即面積插值dim = None # 存儲(chǔ)計(jì)算后的目標(biāo)尺寸w、h(h,w) = image.shape[:2] # 返回輸入圖像高寬if width is None and height is None: # 判斷是否指定了寬和高大小,如果沒(méi)有指定則返回原圖return imageif width is None: # 判斷如果沒(méi)有指定寬度大小,則表示指定了高度大小,那么運(yùn)行內(nèi)部代碼r = height/float(h) # 指定高度與原圖高度的比值dim = (int(w*r),height) # 寬度乘以比值得到新的寬度,此處得到新的寬高else: # 此處表示為width不是None,即指定了寬度,與上述方法一致,計(jì)算比值r = width/float(w)dim = (width,int(h*r))resized = cv2.resize(image,dim,interpolation=inter) # 指定圖像大小為上述的dim,inter默認(rèn)為cV2.INTER_AREA,即面積插值,適用于縮放圖像。return resized
3、定義輪廓點(diǎn)的排序函數(shù)
def order_points(pts): # 對(duì)輸入的四個(gè)點(diǎn)按照左上、右上、右下、左下進(jìn)行排序rect = np.zeros((4,2),dtype='float32') # 創(chuàng)建一個(gè)4*2的數(shù)組,用來(lái)存儲(chǔ)排序之后的坐標(biāo)位置# 按順序找到對(duì)應(yīng)坐標(biāo)0123分別是左上、右上、右下、左下s = pts.sum(axis=1) # 對(duì)pts矩陣的每個(gè)點(diǎn)的x y相加rect[0] = pts[np.argmin(s)] # np.argmin(s)表示數(shù)組s中最小值的索引,表示左上的點(diǎn)的坐標(biāo)rect[2] = pts[np.argmax(s)] # 返回最大值索引,即右下角的點(diǎn)坐標(biāo)diff = np.diff(pts,axis=1) # 對(duì)pts矩陣的每一行的點(diǎn)求差值rect[1] = pts[np.argmin(diff)] # 差值最小的點(diǎn)為右上角點(diǎn)rect[3] = pts[np.argmax(diff)] # 差值最大表示左下角點(diǎn)return rect # 返回排序好的四個(gè)點(diǎn)的坐標(biāo)
4、定義透視變換函數(shù)
# 將透視扭曲的矩形變換成一個(gè)規(guī)則的矩陣
def four_point_transform(image,pts):# 獲取輸入坐標(biāo)點(diǎn)rect = order_points(pts) # 為上述排序的四個(gè)點(diǎn)(tl,tr,br,bl) = rect # 分別返回給四個(gè)值,分別表示為左上、右上、右下、左下# 計(jì)算輸入的w和h值widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1]-bl[1]) ** 2)) # 計(jì)算四邊形底邊的寬度widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1]-tl[1]) ** 2)) # 計(jì)算頂邊的寬度maxWidth = max(int(widthA), int(widthB)) # 返回最大寬度heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2)) # 計(jì)算左上角到右下角的對(duì)角線長(zhǎng)度heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2)) # 計(jì)算右上角到左下角的高的長(zhǎng)度maxHeight = max(int(heightA),int(heightB)) # 返回最長(zhǎng)的高度# 變換后對(duì)應(yīng)坐標(biāo)位置dst = np.array([[0,0], # 定義四個(gè)點(diǎn),表示變換后的矩陣的角點(diǎn)[maxWidth-1,0],[maxWidth-1,maxHeight-1],[0,maxHeight-1]],dtype='float32')M = cv2.getPerspectiveTransform(rect,dst) # 根據(jù)原始點(diǎn)和變換后的點(diǎn)計(jì)算透視變換矩陣Mwarped = cv2.warpPerspective(image,M,(maxWidth,maxHeight)) # 對(duì)原始圖像,針推變換矩陣和輸出圖像大小進(jìn)行透視變換,返回變換后的圖片# 返回變換后的結(jié)果return warped
5、讀取原圖并縮放
# # 讀取輸入
image = cv2.imread('fapiao.jpg') # 讀取原圖
cv_show('image',image) # 展示原圖# 圖片過(guò)大,進(jìn)行縮小處理
ratio = image.shape[0] / 500.0 # 計(jì)算縮小比率,[0]表示圖像的高
orig = image.copy() # 對(duì)原圖復(fù)制生成副本
image = resize(orig, height=500) # 更改圖像尺寸,輸入高度自動(dòng)生成寬度
cv_show('1',image) # 展示縮放后的圖片
????????運(yùn)行結(jié)果:
6、進(jìn)行輪廓檢測(cè)
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) # 灰度圖edged = cv2.threshold(gray,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] # 進(jìn)行二值化,cv2.THRESH_OTSU自動(dòng)尋找最優(yōu)全局閾值,255表示高于最優(yōu)閾值時(shí)將其更改為255
cnts = cv2.findContours(edged.copy(),cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)[1] # 輪廓檢測(cè)
# cv2.RETR_LIST表示檢索所有輪廓,但是不建立層次關(guān)系
# cv2.CHAIN_APPROX_SIMPLE 表示只保存輪廓拐點(diǎn)的信息
# 總體返回處理的圖像、輪廓列表、層次結(jié)構(gòu),這里返回索引為1,表示返回輪廓列表image_contours = cv2.drawContours(image.copy(),cnts,-1,(0,0,255),1) # 繪制所有輪廓
# 在原始圖像的副本上繪制了輪廓
# 繪制輪廓的位置為上述獲取的拐點(diǎn)信息,繪制線條顏色為紅色BRG(0,0,255),線條粗細(xì)為1個(gè)像素cv_show('image_contours',image_contours) # 展示繪制好的圖片
????????運(yùn)行結(jié)果:
5、繪制最大輪廓
screenCnt = sorted(cnts,key = cv2.contourArea,reverse=True)[0] # 對(duì)上述獲取的輪廓列表,排序依據(jù)是輪廓面積,reverse=True表示降序,[0]表示獲取面積最大的輪廓
peri = cv2.arcLength(screenCnt,True) # 計(jì)算最大輪廓的周長(zhǎng)
screenCnt = cv2.approxPolyDP(screenCnt,0.02*peri,True) # 輪廓近似,近似為一個(gè)多邊形,表示新的輪廓與原來(lái)的輪廓最大距離不超過(guò)原始輪廓寬度的0.02倍,True表示輪廓為閉合的
image_contour = cv2.drawContours(image.copy(),[screenCnt],-1,(0,255,0),2) # 繪制輪廓,將上述找到的輪廓繪制到原圖的副本上
cv2.imshow('image_contour',image_contour)
cv2.waitKey(0)
????????運(yùn)行結(jié)果:
6、對(duì)最大輪廓進(jìn)行透視變換
warped = four_point_transform(orig,screenCnt.reshape(4,2)*ratio) # 輸入?yún)?shù)原圖,將最大輪廓圖形狀改變?yōu)?*2的格式,即四個(gè)點(diǎn),然后乘以上述定義的比率來(lái)縮放輪廓
cv2.imwrite('invoice_new.jpg',warped) # 將經(jīng)過(guò)透視變換處理的圖片存入本地
cv2.namedWindow('xx',cv2.WINDOW_NORMAL) # 設(shè)置一個(gè)窗口,名稱為xx,這個(gè)窗口大小用戶可通過(guò)拖動(dòng)隨意調(diào)節(jié)大小
cv2.imshow('xx',warped) # 展示經(jīng)過(guò)透視變換處理的圖片
cv2.waitKey(0)
????????運(yùn)行結(jié)果:
7、旋轉(zhuǎn)、二值化處理
# 二值處理
warped = cv2.cvtColor(warped,cv2.COLOR_BGR2GRAY) # 導(dǎo)入新的圖片的灰度圖
ref = cv2.threshold(warped,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1] # 對(duì)灰度圖進(jìn)行二值化處理kernel = np.ones((2,2),np.uint8) # 設(shè)置一個(gè)單位矩陣,大小為2*2,表示設(shè)置核kernel的大小
ref_new = cv2.morphologyEx(ref,cv2.MORPH_CLOSE,kernel) # 閉運(yùn)算,先膨脹再腐蝕
ref_new = resize(ref_new.copy(),width=500) # 對(duì)閉運(yùn)算處理完的圖像重置大小
cv_show('yy',ref_new)
rotated_image = cv2.rotate(ref_new,cv2.ROTATE_90_COUNTERCLOCKWISE) # 對(duì)圖像逆時(shí)針旋轉(zhuǎn)90度
cv2.imshow('result',rotated_image)
cv2.waitKey(0)