openCV提取影象中的矩形區域
阿新 • • 發佈:2020-07-23
改編自詳解利用OpenCV提取影象中的矩形區域(PPT螢幕等) 原文是c++版,我改成了python版,供大家參考學習。
主要思想:邊緣檢測—》輪廓檢測—》找出最大的面積的輪廓—》找出頂點—》投影變換
import numpy as np import cv2 # 這個成功的扣下了ppt白板 srcPic = cv2.imread('2345.jpg') length=srcPic.shape[0] depth=srcPic.shape[1] polyPic = srcPic shrinkedPic = srcPic greyPic = cv2.cvtColor(shrinkedPic,cv2.COLOR_BGR2GRAY) ret,binPic = cv2.threshold(greyPic,130,255,cv2.THRESH_BINARY) print(binPic.shape) median = cv2.medianBlur(binPic,5) # 進行邊緣檢測 cannyPic = cv2.Canny(median,10,200) cv2.namedWindow("binary",0) cv2.namedWindow("binary2",0) cv2.imshow("binary",cannyPic) # 找出輪廓 contours,hierarchy = cv2.findContours(cannyPic,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE) cv2.imwrite('binary2.png',cannyPic) cv2.imshow("binary2",cannyPic) i = 0 maxArea = 0 # 挨個檢檢視那個輪廓面積最大 for i in range(len(contours)): if cv2.contourArea(contours[i]) > cv2.contourArea(contours[maxArea]): maxArea = i #檢查輪廓得到分佈在四個角上的點 hull = cv2.convexHull(contours[maxArea]) s = [[1,2]] z = [[2,3]] for i in hull: s.append([i[0][0],i[0][1]]) z.append([i[0][0],i[0][1]]) del s[0] del z[0] #現在的目標是從一堆點中挑出分佈在四個角落的點,決定把圖片分為四等份,每個區域的角度來劃分點, #預設四個角分別分佈在影象的四等分的區間上,也就是矩形在影象中央 # 我們把所有點的座標,都減去圖片中央的那個點(當成原點),然後按照x y座標值的正負 判斷屬於哪一個區間 center=[length/2,depth/2] # 可以得到小數 for i in range(len(s)): s[i][0] = s[i][0] - center[0] s[i][1] = s[i][1] - center[1] one = [] two = [] three = [] four = [] # 判斷是那個區間的 for i in range(len(z)): if s[i][0] <= 0 and s[i][1] <0 : one.append(i) elif s[i][0] > 0 and s[i][1] <0 : two.append(i) elif s[i][0] >= 0 and s[i][1] > 0: four.append(i) else:three.append(i) p=[] distance=0 temp = 0 # 下面開始判斷每個區間的極值,要選擇距離中心點最遠的點,就是角點 for i in one : x=z[i][0]-center[0] y=z[i][1]-center[1] d=x*x+y*y if d > distance : temp = i distance = d p.append([z[temp][0],z[temp][1]]) distance=0 temp=0 for i in two : x=z[i][0]-center[0] y=z[i][1]-center[1] d=x*x+y*y if d > distance : temp = i distance = d p.append([z[temp][0],z[temp][1]]) distance=0 temp=0 for i in three : x=z[i][0]-center[0] y=z[i][1]-center[1] d=x*x+y*y if d > distance : temp = i distance = d p.append([z[temp][0],z[temp][1]]) distance=0 temp=0 for i in four : x=z[i][0]-center[0] y=z[i][1]-center[1] d=x*x+y*y if d > distance : temp = i distance = d p.append([z[temp][0],z[temp][1]]) for i in p: cv2.circle(polyPic,(i[0],i[1]),2,(0,0),2) # 給四個點排一下順序 a=[] b=[] st=[] for i in p: a.append(i[0]) b.append(i[1]) index=np.lexsort((b,a)) for i in index: st.append(p[i]) p = st print(p) pts1 = np.float32([[p[0][0],p[0][1]],[p[1][0],p[1][1]],[p[2][0],p[2][1]],[p[3][0],p[3][1]]]) # dst=np.float32([[0,0],[0,srcPic.shape[1]],[srcPic.shape[0],srcPic.shape[1]]]) dst=np.float32([[0,600],[400,600]]) # 投影變換 M = cv2.getPerspectiveTransform(pts1,dst) cv2.namedWindow("srcPic2",0) cv2.imshow("srcPic2",srcPic) #dstImage = cv2.warpPerspective(srcPic,M,(srcPic.shape[0],srcPic.shape[1])) dstImage = cv2.warpPerspective(srcPic,(400,600)) # 在原圖上畫出紅色的檢測痕跡,先生成一個黑色圖 black = np.zeros((shrinkedPic.shape[0],shrinkedPic.shape[1]),dtype=np.uint8) # 二值圖轉為三通道圖 black3 = cv2.merge([black,black,black]) # black=black2 cv2.drawContours(black,contours,maxArea,11) cv2.drawContours(black3,(255,11) cv2.imwrite('cv.png',black) cv2.namedWindow("cannyPic",0) cv2.imshow("cannyPic",black) cv2.namedWindow("shrinkedPic",0) cv2.imshow("shrinkedPic",polyPic) cv2.namedWindow("dstImage",0) cv2.imshow("dstImage",dstImage) # 等待一個按下鍵盤事件 cv2.waitKey(0) # 銷燬所有創建出的視窗
執行效果
用到的圖片
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。