计算机视觉-计算机视觉开源库OpenCV基础
1、加載、顯示、保存圖像
import argparse import cv2ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="Path to the image")#讀取指定指令,獲取圖片。參數(shù)1:輸入指令的頭字母,參數(shù)2:需要輸入的指令 args = vars(ap.parse_args())image = cv2.imread(args["image"]) #讀取指定參數(shù)的,讀取照片 print "width: %d pixels" % (image.shape[1]) # 獲取圖像的寬度,橫向尺寸,圖像坐標(biāo)系中,第二個(gè)參數(shù) print "height: %d pixels" % (image.shape[0] )#獲取圖像的高度,豎向尺寸,圖像坐標(biāo)系中,第一個(gè)參數(shù) 注意:讀取圖像x,y互換 print "channels: %d" % (image.shape[2])cv2.imshow("Image", image)#顯示圖片 cv2.imwrite("newimage.jpg", image) #將圖片寫入指定路徑 cv2.waitKey(0)#等待程序結(jié)束2、圖像基礎(chǔ)
(h, w) = image.shape[:2] #(x,y)像素中的顯示,獲取圖片的高度(x),獲取圖片的寬度(y)(b, g, r) = image[0, 0] #獲取指定位置的像素,存儲(chǔ)方式為bgr(cX, cY) = (w / 2, h / 2) #cX:圖片的寬度,cY:圖片高度 tl = image[0:cY, 0:cX] #獲取圖片的左上角部分[起始點(diǎn)x坐標(biāo):終點(diǎn)x坐標(biāo),起點(diǎn)的y坐標(biāo):終點(diǎn)y坐標(biāo)],得出的值分別指高度和寬度#運(yùn)用像素指定位置賦值方法,向Background圖片上插入圖片resized_leftfor left_x in xrange(0, 500, 1):for left_y in xrange(0, 500, 1):Background[400 + left_x, 20 + left_y] = resized_left[left_x, left_y]3、繪圖
canvas = np.zeros((300, 300, 3), dtype="uint8") #設(shè)置畫布尺寸green = (0, 255, 0)#設(shè)置線條顏色 cv2.line(canvas, (0, 0), (300, 300), green) #參數(shù)1:指定畫布,參數(shù)2:線條的開始位置,參數(shù)3:線條終點(diǎn)位置,參數(shù)4:線條顏色 cv2.line(canvas, (300, 0), (0, 300), red, 3) #參數(shù)5:線條像素厚度cv2.rectangle(canvas, (10, 10), (60, 60), green)#參數(shù)1:指定畫布,參數(shù)2:矩形起點(diǎn)位置,參數(shù)3:矩形對(duì)角線點(diǎn)的位置,線條顏色 cv2.rectangle(canvas, (50, 200), (200, 225), red, 5)#參數(shù)5:線條寬度,負(fù)數(shù)表示填充矩形(centerX, centerY) = (canvas.shape[1] / 2, canvas.shape[0] / 2)#設(shè)置圓心坐標(biāo) white = (255, 255, 255)#設(shè)置圓的線條顏色cv2.circle(canvas, (centerX, centerY), r, white)#參數(shù)1:畫布,參數(shù)2:圓心點(diǎn),參數(shù)3:設(shè)置圓的半徑,設(shè)置畫圓的線條顏色cv2.circle(canvas, tuple(pt), radius, color, -1)#參數(shù)4:設(shè)置畫圓的線條粗細(xì),如果為負(fù)數(shù),表示填充圓4、圖像處理
4.1、翻譯
M = np.float32([[1, 0, -50], [0, 1, -90]]) #定義翻譯矩陣 :參數(shù)1:[1,0,x]:x表示像素向左或者向右移動(dòng)個(gè)數(shù),x為負(fù)值圖像左移,正值為右移定。參數(shù)2:[0,1,y]:y表示像素上下移動(dòng),y為負(fù)值向上移動(dòng),正值向下移動(dòng)。記憶口訣:前左負(fù)右正,后上負(fù)下正 shifted = cv2.warpAffine(image, M, (image.shape[1],image.shape[0]))#對(duì)矩陣進(jìn)行翻譯 參數(shù)1:翻譯的目標(biāo)圖像,參數(shù)2:翻譯的矩陣,參數(shù)3:翻譯后圖像大小#imutils模塊的翻譯函數(shù) shifted = imutils.translate(image, 0, 100)#參數(shù)1:移動(dòng)的目標(biāo)圖像,參數(shù)2:左右移動(dòng)的值,參數(shù)3:上下移動(dòng)的值注:不會(huì)改變圖像大小。?
4.2、旋轉(zhuǎn)
注:運(yùn)用翻譯將圖片移到中心位置,四周留出黑色邊框,在運(yùn)用旋轉(zhuǎn)(旋轉(zhuǎn)角度為0),可將圖片放大
(h, w) = image.shape[:2] #獲取圖像的高和寬 (cX, cY) = (w / 2, h / 2) #獲取圖像的中心點(diǎn)M = cv2.getRotationMatrix2D((cX, cY), 45, 1.0) #設(shè)置旋轉(zhuǎn)矩陣,參數(shù)1:旋轉(zhuǎn)點(diǎn) 參數(shù)2:旋轉(zhuǎn)角度,正值逆時(shí)針旋轉(zhuǎn),負(fù)值順時(shí)針選裝,參數(shù)3:旋轉(zhuǎn)后圖像與原始圖像的比例,圖像原始大小不會(huì)發(fā)生變化,類似相機(jī)焦距變化 rotated = cv2.warpAffine(image, M, (w, h)) #參數(shù)1:目標(biāo)圖像,參數(shù)2:旋轉(zhuǎn)矩陣,參數(shù)3#旋轉(zhuǎn)后的圖像尺寸#imutils模塊的旋轉(zhuǎn)函數(shù) rotated = imutils.rotate(image, 180) #參數(shù)1:旋轉(zhuǎn)目標(biāo)圖片 參數(shù)2:旋轉(zhuǎn)角度 center=(x,y)可以設(shè)置旋轉(zhuǎn)點(diǎn)4.3、圖像大小調(diào)整
注:改變?cè)紙D片的實(shí)際大小
r = 150.0 / image.shape[1] #新圖像與舊圖像的寬比例 注:方便圖片按原比例縮放 dim = (150, int(image.shape[0] * r)) #設(shè)置新圖像的像素尺寸 resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA) #調(diào)整圖像大小,返回一個(gè)新圖像#運(yùn)用imutils中的resize函數(shù) resized = imutils.resize(image, width=100) #參數(shù)1:目標(biāo)圖像,參數(shù)2:設(shè)置新圖像的寬度,可以為height,運(yùn)用高度#運(yùn)用插值方法縮放大圖片,,通過不同的像素填充方法放大圖片。 resized = imutils.resize(image, width=image.shape[1] * 3, inter=method)#參數(shù)1:目標(biāo)圖片,參數(shù)2:處理后圖片像素寬(整形),參數(shù)3:像素處理方法 """method: cv2.INTER_NEAREST:最近鄰內(nèi)插值cv2.INTER_LINEAR:雙線性插值cv2.INTER_AREA:區(qū)域插值cv2.INTER_CUBIC:雙三次插值cv2.INTER_LANCZOS4 :雙三次插值4.4、圖像翻轉(zhuǎn)
flipped = cv2.flip(image, 1)#水平翻轉(zhuǎn) flipped = cv2.flip(image, 0)#上下翻轉(zhuǎn) flipped = cv2.flip(image, -1)#水平翻轉(zhuǎn)后上下翻轉(zhuǎn)4.5、圖像裁剪
face = image[85:250, 85:220] #參數(shù)1:裁切高度 x開始位置:x結(jié)束位置,參數(shù)2:裁切寬度 y開始位置:y結(jié)束位置,返回新圖片4.6、圖像像素像素值操作
注:修改圖片的亮度
M = np.ones(image.shape, dtype = "uint8") * 100 #設(shè)置與圖片大下相同的矩陣,矩陣填充值為100 added = cv2.add(image, M)#將原始圖片與新矩陣相加,像素亮度提高100M = np.ones(image.shape, dtype = "uint8") * 50#設(shè)置與圖片大下相同的矩陣,矩陣填充值為50 subtracted = cv2.subtract(image, M)#將原始圖片與新矩陣相減,像素亮度降低504.7、按位操作
注:主要是黑白圖像處理
bitwiseAnd = cv2.bitwise_and(rectangle, circle)#當(dāng)且僅當(dāng)倆個(gè)相同位置的像素大于0,才返回真 bitwiseOr = cv2.bitwise_or(rectangle, circle)#倆個(gè)相同位置的像素有一個(gè)大于0,返回真 bitwiseXor = cv2.bitwise_xor(rectangle, circle)#當(dāng)且僅當(dāng)倆個(gè)相同位置的像素只有一個(gè)大于0,才返回真 bitwiseNot = cv2.bitwise_not(circle)#像素值取反4.8、掩蔽
注:提取圖像中感興趣的部分,遮掩的必須用關(guān)鍵字mask
mask = np.zeros(image.shape[:2], dtype="uint8") #設(shè)置掩蔽畫布的大小 cv2.rectangle(mask, (0, 90), (290, 450), 255, -1)#設(shè)置不掩蔽的地方 masked = cv2.bitwise_and(image, image, mask=mask)#圖片顯示的區(qū)域4.9、像素分割與合并
(B, G, R) = cv2.split(image) #像素分離圖像,B,G,R圖像的值為整數(shù),非BGR像素矩陣組成,其值是如何轉(zhuǎn)變的?merged = cv2.merge([B, G, R]) #三個(gè)色彩合并,還原為彩色圖像,像素由BGR像素矩陣組成zeros = np.zeros(image.shape[:2], dtype = "uint8")#建立一個(gè)二值畫布,與各個(gè)色彩通道合并,像是各個(gè)色彩通道的影響 cv2.imshow("Red", cv2.merge([zeros, zeros, R]))#只有紅色的圖片 cv2.imshow("Green", cv2.merge([zeros, G, zeros]))#只有綠色的圖片 cv2.imshow("Blue", cv2.merge([B, zeros, zeros]))#只有藍(lán)色的圖片問:如何從BGR轉(zhuǎn)換成整數(shù)值
5、內(nèi)核
略
6、形態(tài)操作
image = cv2.imread(args["image"]) #打開一張圖片 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)#將圖片轉(zhuǎn)為二值劃#侵蝕 將前景物體變小,理解成將圖像斷開裂縫變大(在圖片上畫上黑色印記,印記越來越大) for i in xrange(0, 3):eroded = cv2.erode(gray.copy(), None, iterations=i + 1)#參數(shù)1:需要侵蝕的圖像,參數(shù)2:結(jié)構(gòu)元素() 參數(shù)3:迭代次數(shù),值越大,侵蝕越嚴(yán)重cv2.imshow("Eroded {} times".format(i + 1), eroded)cv2.waitKey(0)#擴(kuò)張 將前景物體變大,理解成將圖像斷開裂縫變小(在圖片上畫上黑色印記,印記越來越小) for i in xrange(0, 3):dilated = cv2.dilate(gray.copy(), None, iterations=i + 1)#參數(shù)1:需要侵蝕的圖像,參數(shù)2:結(jié)構(gòu)元素() 參數(shù)3:迭代次數(shù),值越大,擴(kuò)張?jiān)酱骳v2.imshow("Dilated {} times".format(i + 1), dilated)cv2.waitKey(0)#開盤 應(yīng)用侵蝕以去除小斑點(diǎn),然后應(yīng)用擴(kuò)張以重新生成原始對(duì)象的大小,用于消除雜質(zhì) kernelSizes = [(3, 3), (5, 5), (7, 7)]#定義結(jié)構(gòu)化元素的寬度和高度for kernelSize in kernelSizes:kernel = cv2.getStructuringElement(cv2.MORPH_RECT, kernelSize) #參數(shù)1:結(jié)構(gòu)化元素的類型 參數(shù)2:構(gòu)造元素的大小opening = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel)#參數(shù)1:形態(tài)學(xué)運(yùn)算的圖像 參數(shù)2:形態(tài)操作的實(shí)際 類型 參數(shù)3:內(nèi)核/結(jié)構(gòu)化元素cv2.imshow("Opening: ({}, {})".format(kernelSize[0], kernelSize[1]), opening)cv2.waitKey(0)"""形態(tài)操作實(shí)際類型:cv2.MORPH_CLOSE(閉幕):用于封閉對(duì)象內(nèi)的孔或?qū)⒔M件連接在一起cv2.MORPH_GRADIENT(形態(tài)梯度):用于確定圖像的特定對(duì)象的輪廓 """ #頂帽/黑帽 顯示黑色背景上的圖像的 明亮區(qū)域。適合于灰度圖像 rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (13, 5))#定義寬度為13 像素和高度為 5像素的 矩形 結(jié)構(gòu)元素 blackhat = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, rectKernel)#參數(shù)1:形態(tài)學(xué)運(yùn)算的圖像 參數(shù)2:形態(tài)操作的實(shí)際 類型 參數(shù)3:內(nèi)核/結(jié)構(gòu)化元素tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel) #參數(shù)1:形態(tài)學(xué)運(yùn)算的圖像 參數(shù)2:形態(tài)操作的實(shí)際 類型 參數(shù)3:內(nèi)核/結(jié)構(gòu)化元素?7、平滑和模糊
kernelSizes = [(3, 3), (9, 9), (15, 15)] #定義內(nèi)核大小參數(shù)列表,內(nèi)核越大,模糊越明顯# loop over the kernel sizes and apply an "average" blur to the image for (kX, kY) in kernelSizes:blurred = cv2.blur(image, (kX, kY))#使用平均模糊方法,參數(shù)1:模糊對(duì)象,參數(shù)2:矩陣大小cv2.imshow("Average ({}, {})".format(kX, kY), blurred)cv2.waitKey(0) """模糊方法:平均模糊:過度模糊圖像并忽略重要的邊緣blurred =cv2.blur(image, (kX, kY))高斯:保留更多的圖像邊緣blurred =cv2.GaussianBlur(image, (kX, kY), 0)參數(shù)1:模糊對(duì)象,參數(shù)2:矩陣大小 參數(shù)3:標(biāo)準(zhǔn)方差 中位數(shù)模糊: 圖像中去除鹽和胡椒,圖像中的雜質(zhì)點(diǎn)blurred = cv2.medianBlur(image, k)參數(shù)1:模糊對(duì)象,參數(shù)2:中位數(shù)值,為整型數(shù)據(jù),數(shù)據(jù)越大圖像越模糊雙邊模糊: 減少噪音同時(shí)仍然保持邊緣,我們可以使用雙邊模糊。雙邊模糊通過引入兩個(gè)高斯分布來實(shí)現(xiàn)blurred =cv2.bilateralFilter(image, diameter, sigmaColor, sigmaSpace)參數(shù)1:想要模糊的圖像。參數(shù)2:像素鄰域的直徑 - 這個(gè)直徑越大,模糊計(jì)算中包含的像素越多。參數(shù)3:顏色標(biāo)準(zhǔn)差,模糊時(shí)將考慮鄰域中的更多顏色,相似顏色的像素才能顯著地影響模糊,參數(shù)4:空間標(biāo)準(zhǔn)偏差,更大的值意味著像素越遠(yuǎn)離中心像素直徑 將影響模糊計(jì)算。后面3個(gè)參數(shù)都為整型參數(shù) """8、照明和色彩空間
#RGB 紅、黃、藍(lán)組成的顏色矩陣,每個(gè)色度值范圍[0,255] image = cv2.imread(args["image"]) for (name, chan) in zip(("B", "G", "R"), cv2.split(image)):cv2.imshow(name, chan)#HSV 色調(diào)(H):們正在研究哪種“純”的顏色。飽和度(S):顏色如何“白,例如純紅,隨著零飽和度的顏色是純白色。價(jià)值(V):該值允許我們控制我們的顏色的亮度,零值表示純黑色 hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) for (name, chan) in zip(("H", "S", "V"), cv2.split(hsv)):cv2.imshow(name, chan)#L * a * b *表 L通道:像素的“亮度”。a通道:源于L通道的中心,在頻譜的一端定義純綠色,另一端定義純紅色。b通道: 也來自于L通道的中心,但是垂直于a通道。 lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB) for (name, chan) in zip(("L*", "a*", "b*"), cv2.split(lab)):cv2.imshow(name, chan)#灰度:轉(zhuǎn)換成灰度級(jí)時(shí),每個(gè)RGB通道 不是 均勻加權(quán) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)9、閥值
閥值:圖像的二值化
image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)#將圖像二值化 blurred = cv2.GaussianBlur(gray, (7, 7), 0)(T,threshInv)=cv2.threshold(blurred,200,255,cv2.THRESH_BINARY_INV) #參數(shù)1:希望閾值的灰度圖像。參數(shù)2:手動(dòng)提供我們的T閾值。參數(shù)3:設(shè)置輸出值。參數(shù)4:閾值方法(白色背景,黑色圖),將像素值小于參數(shù)2的值換成參數(shù)3輸出,大于參數(shù)2的值,輸出值為0 cv2.imshow("Threshold Binary Inverse", threshInv)(T, thresh) =cv2.threshold(blurred,200,255,cv2.THRESH_BINARY)#參數(shù)1:希望閾值的灰度圖像。參數(shù)2:手動(dòng)提供我們的T閾值。參數(shù)3:設(shè)置輸出值。參數(shù)4:閾值方法(黑背景,白色圖),將像素值大于參數(shù)2的值換成參數(shù)3輸出,小于參數(shù)2的值,輸出值為0。 cv2.imshow("Threshold Binary", thresh)cv2.imshow("Output", cv2.bitwise_and(image, image, mask=threshInv))#大津方法 參數(shù)1:希望閾值的灰度圖像。參數(shù)2:大津的方法將自動(dòng)計(jì)算出我們的T的最優(yōu)值。參數(shù)3:閾值的輸出值,只要給定像素通過閾值測(cè)試。參數(shù)4:對(duì)應(yīng)于Otsu的閾值法 (T, threshInv) = cv2.threshold(blurred, 0, 255,cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)#自適應(yīng)閥值法:參數(shù)1:希望閾值的灰度圖像。參數(shù)2:參數(shù)是輸出閾值。參數(shù)3:自適應(yīng)閾值法。參數(shù)4:閾值方法。參數(shù)5:是我們的像素鄰域大小。參數(shù)6:微調(diào) 我們的閾值 thresh=cv2.adaptiveThreshold(blurred,255,cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 25, 15) thresh =threshold_adaptive(blurred,29,offset=5).astype("uint8")* 255 thresh = cv2.bitwise_not(thresh)#閾值適配函數(shù)執(zhí)行自適應(yīng)閾值10.1、圖像漸變
圖像漸變:圖像梯度主要應(yīng)用與邊緣檢測(cè)
#Sobel內(nèi)核 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)gX = cv2.Sobel(gray, ddepth=cv2.CV_64F, dx=1, dy=0) #計(jì)算x方向的梯度 gY = cv2.Sobel(gray, ddepth=cv2.CV_64F, dx=0, dy=1) #計(jì)算y方向的梯度gX = cv2.convertScaleAbs(gX) #轉(zhuǎn)換回8位無符號(hào)整型 gY = cv2.convertScaleAbs(gY) #轉(zhuǎn)換回8位無符號(hào)整型sobelCombined = cv2.addWeighted(gX, 0.5, gY, 0.5, 0) #將倆個(gè)圖像組合成單個(gè)圖像gX = cv2.Sobel(gray, cv2.CV_64F, 1, 0) #計(jì)算x梯度方向 gY = cv2.Sobel(gray, cv2.CV_64F, 0, 1) #計(jì)算y梯度方向mag = np.sqrt((gX ** 2) + (gY ** 2)) #梯度幅度計(jì)算:平方梯度的平方根 X和 ? 相加 orientation = np.arctan2(gY, gX) * (180 / np.pi) % 180 #梯度方向計(jì)算:兩個(gè)梯度的反正切idxs = np.where(orientation >= args["lower_angle"], orientation, -1)#手柄選擇,參數(shù)1: 函數(shù)是我們要測(cè)試的條件,尋找大于最小提供角度的索引。參數(shù)2:要檢查的陣列在哪里。參數(shù)3:特定值設(shè)置為-1。 idxs = np.where(orientation <= args["upper_angle"], idxs, -1) mask = np.zeros(gray.shape, dtype="uint8")#構(gòu)造一個(gè) 掩碼 - 所有具有相應(yīng)idxs 值> -1的坐標(biāo) 都設(shè)置為 255 (即前景)。否則,它們保留為 0(即背景) mask[idxs > -1] = 25510.2、邊緣檢測(cè)
邊緣類型:
步邊:階躍邊緣形式當(dāng)存在來自不連續(xù)到另一的一側(cè)的像素強(qiáng)度的突然變化
斜坡邊緣:斜坡邊緣就像一個(gè)階躍邊緣,僅在像素強(qiáng)度的變化不是瞬時(shí)的。相反,像素值的變化發(fā)生短而有限的距離
嶺邊:脊邊緣是相似于兩個(gè)結(jié)合??斜坡邊緣,一個(gè)右對(duì)另一碰撞
屋頂邊:頂部有一個(gè)短而有限的高原的邊緣不同
?邊緣檢測(cè)法:
11.1、查找和繪制輪廓
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)(cnts, _) = cv2.findContours(gray.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)#參數(shù)1:需要繪制輪廓的圖像。參數(shù)2:返回的輪廓數(shù)量的標(biāo)志。參數(shù)3:輪廓壓縮類型。返回值:第一個(gè)值是輪廓本上。第二個(gè)值是要檢查的輪廓層次結(jié)構(gòu) clone = image.copy() cv2.drawContours(clone, cnts, -1, (0, 255, 0), 2)#參數(shù)1:要繪制輪廓的圖像。參數(shù)2:使用的輪廓列表。參數(shù)3:cnts列表中的輪廓索引,-1表示繪制所有輪廓,0是僅畫第一個(gè),1表示繪制第二個(gè)輪廓。參數(shù)3:繪制輪廓的顏色。參數(shù)4:繪制輪廓線的像素 #輪廓單個(gè)繪制 for (i, c) in enumerate(cnts):print "Drawing contour #{}".format(i + 1)cv2.drawContours(clone, [c], -1, (0, 255, 0), 2)cv2.imshow("Single Contour", clone)cv2.waitKey(0)#返回所有輪廓外觀: (cnts, _) = cv2.findContours(gray.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)#輪廓外觀與掩碼的一起使用 for c in cnts:# construct a mask by drawing only the current contourmask = np.zeros(gray.shape, dtype="uint8")cv2.drawContours(mask, [c], -1, 255, -1)# show the imagescv2.imshow("Image", image)cv2.imshow("Mask", mask)cv2.imshow("Image + Mask", cv2.bitwise_and(image, image, mask=mask))#補(bǔ)充:運(yùn)用霍夫找圓心 gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #輸出圖像大小,方便根據(jù)圖像大小調(diào)節(jié)minRadius和maxRadius print(img.shape) #霍夫變換圓檢測(cè) circles= cv2.HoughCircles(gray,cv2.HOUGH_GRADIENT,1,100,param1=100,param2=30,minRadius=5,maxRadius=300) #輸出返回值,方便查看類型 print(circles) #輸出檢測(cè)到圓的個(gè)數(shù) print(len(circles[0])) #根據(jù)檢測(cè)到圓的信息,畫出每一個(gè)圓 for circle in circles[0]:#圓的基本信息print(circle[2])#坐標(biāo)行列x=int(circle[0])y=int(circle[1])#半徑r=int(circle[2])#在原圖用指定顏色標(biāo)記出圓的位置img=cv2.circle(img,(x,y),r,(0,0,255),-1) #顯示新圖像 cv2.imshow('res',img)11.2、簡(jiǎn)單的輪廓屬性
質(zhì)心:質(zhì)心”或“質(zhì)心”?是圖像中物體的中心??(x,y)坐標(biāo)
#繪制輪廓質(zhì)心 (cnts, _) = cv2.findContours(gray.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) clone = image.copy()for c in cnts:# compute the moments of the contour which can be used to compute the# centroid or "center of mass" of the regionM = cv2.moments(c)cX = int(M["m10"] / M["m00"])cY = int(M["m01"] / M["m00"])# draw the center of the contour on the imagecv2.circle(clone, (cX, cY), 10, (0, 255, 0), -1)面積和周長(zhǎng):輪廓的面積是輪廓輪廓內(nèi)部的像素?cái)?shù)。類似地,??周長(zhǎng)??(有時(shí)稱為??弧長(zhǎng))是輪廓的長(zhǎng)度
#獲取輪廓的面積與周長(zhǎng) for (i, c) in enumerate(cnts):area = cv2.contourArea(c)perimeter = cv2.arcLength(c, True)print "Contour #%d -- area: %.2f, perimeter: %.2f" % (i + 1, area, perimeter)cv2.drawContours(clone, [c], -1, (0, 255, 0), 2)#計(jì)算圖像的質(zhì)心,并在圖像上顯示輪廓數(shù),以便我們可以將形狀與終端輸出相關(guān)聯(lián)。M = cv2.moments(c)cX = int(M["m10"] / M["m00"])#?cY = int(M["m01"] / M["m00"])#?cv2.putText(clone, "#%d" % (i + 1), (cX - 20, cY), cv2.FONT_HERSHEY_SIMPLEX,1.25, (255, 255, 255), 4)邊框:邊界”和“包含”整個(gè)圖像的輪廓區(qū)域
for c in cnts:# fit a bounding box to the contour(x, y, w, h) = cv2.boundingRect(c)cv2.rectangle(clone, (x, y), (x + w, y + h), (0, 255, 0), 2)旋轉(zhuǎn)邊框:
#繪制輪廓的旋轉(zhuǎn)邊框 for c in cnts:# fit a rotated bounding box to the contour and draw a rotated bounding boxbox = cv2.minAreaRect(c)#參數(shù):我們的輪廓。并返回一個(gè)包含3個(gè)值的元組。元組的第一個(gè)值是旋轉(zhuǎn)的邊界框的起始 (x,y)坐標(biāo)。第二個(gè)值是邊界框的寬度和高度。而最終的值就是我們形狀或旋轉(zhuǎn)的角度box = np.int0(cv2.cv.BoxPoints(box))#寬度和高度以及旋轉(zhuǎn)角轉(zhuǎn)換為一組坐標(biāo)點(diǎn)cv2.drawContours(clone, [box], -1, (0, 255, 0), 2)最小封閉圓:
for c in cnts:((x, y), radius) = cv2.minEnclosingCircle(c)#返回圓的中心的(x,y)坐標(biāo)以及圓的 半徑cv2.circle(clone, (int(x), int(y)), int(radius), (0, 255, 0), 2)裝配橢圓:將橢圓擬合到輪廓上很像將輪廓的矩形裝配到輪廓上
for c in cnts:if len(c) >= 5:ellipse = cv2.fitEllipse(c)cv2.ellipse(clone, ellipse, (0, 255, 0), 2)?11.3、高級(jí)輪廓
長(zhǎng)寬比:寬高比=圖像寬度/圖像寬度
程度:邊界框區(qū)域=邊界框?qū)挾萖邊框高度
凸海鷗:歐氏空間中的一組??X點(diǎn),凸包是包含這些X點(diǎn)的最小可能凸集
密實(shí)度:堅(jiān)固度=輪廓面積/凸包面積
#識(shí)別‘X’與‘O’ (cnts, _) = cv2.findContours(gray.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)#獲取輪廓列表for (i, c) in enumerate(cnts):area = cv2.contourArea(c)#獲取輪廓面積(x, y, w, h) = cv2.boundingRect(c)#獲取輪廓的起始坐標(biāo),邊界的寬度和高度hull = cv2.convexHull(c) #獲取形狀的實(shí)際凸包hullArea = cv2.contourArea(hull)#計(jì)算凸包面積solidity = area / float(hullArea)#獲取堅(jiān)固度char = "?"#依據(jù)堅(jiān)固度,判斷圖像的形狀if solidity > 0.9:char = "O"elif solidity > 0.5:char = "X"#繪制輪廓if char != "?":cv2.drawContours(image, [c], -1, (0, 255, 0), 3)cv2.putText(image, char, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1.25,(0, 255, 0), 4)print "%s (Contour #%d) -- solidity=%.2f" % (char, i + 1, solidity)cv2.imshow("Output", image) cv2.waitKey(0) #識(shí)別俄羅斯方塊 (cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)#獲取圖片中的輪廓列表 hullImage = np.zeros(gray.shape[:2], dtype="uint8")for (i, c) in enumerate(cnts):area = cv2.contourArea(c)#獲取輪廓面積(x, y, w, h) = cv2.boundingRect(c)#獲取輪廓邊界aspectRatio = w / float(h)#獲取寬高比extent = area / float(w * h)#獲取當(dāng)前輪廓的范圍hull = cv2.convexHull(c)hullArea = cv2.contourArea(hull)#solidity = area / float(hullArea)#獲取堅(jiān)固度,依據(jù)堅(jiān)固度,判斷物體形狀cv2.drawContours(hullImage, [hull], -1, 255, -1)cv2.drawContours(image, [c], -1, (240, 0, 159), 3)shape = ""11.4、輪廓近似
輪廓逼近:一種用減少的點(diǎn)集合減少曲線中的點(diǎn)數(shù)的算法,簡(jiǎn)單的稱為分裂合并算法
#檢測(cè)圖像中的正方形 import cv2image = cv2.imread("images/circles_and_squares.png") gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)#獲得圖像輪廓列表 (cnts, _) = cv2.findContours(gray.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)#循環(huán)每個(gè)輪廓 for c in cnts:#獲取輪廓的周長(zhǎng)peri = cv2.arcLength(c, True)approx = cv2.approxPolyDP(c, 0.01 * peri, True)if len(approx) == 4:#判斷處理后的輪廓是否有4個(gè)頂點(diǎn)# draw the outline of the contour and draw the text on the imagecv2.drawContours(image, [c], -1, (0, 255, 255), 2)(x, y, w, h) = cv2.boundingRect(approx)cv2.putText(image, "Rectangle", (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX,0.5, (0, 255, 255), 2)cv2.imshow("Image", image) cv2.waitKey(0)物體輪廓檢測(cè):
import cv2image = cv2.imread("images/receipt.png") gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) edged = cv2.Canny(gray, 75, 200)cv2.imshow("Original", image) cv2.imshow("Edge Map", edged)(cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:7]# loop over the contours for c in cnts:peri = cv2.arcLength(c, True)approx = cv2.approxPolyDP(c, 0.01 * peri, True)print "original: {}, approx: {}".format(len(c), len(approx))if len(approx) == 4:cv2.drawContours(image, [approx], -1, (0, 255, 0), 2)cv2.imshow("Output", image) cv2.waitKey(0)11.5、排列輪廓
import numpy as np import argparse import cv2#參數(shù)1:輪廓列表 參數(shù)2:排列方法 def sort_contours(cnts, method="left-to-right"):reverse = Falsei = 0if method == "right-to-left" or method == "bottom-to-top":reverse = Trueif method == "top-to-bottom" or method == "bottom-to-top":i = 1boundingBoxes = [cv2.boundingRect(c) for c in cnts](cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),key=lambda b:b[1][i], reverse=reverse))return (cnts, boundingBoxes)def draw_contour(image, c, i):M = cv2.moments(c)cX = int(M["m10"] / M["m00"])cY = int(M["m01"] / M["m00"])cv2.putText(image, "#{}".format(i + 1), (cX - 20, cY), cv2.FONT_HERSHEY_SIMPLEX,1.0, (255, 255, 255), 2)return imageap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="Path to the input image") ap.add_argument("-m", "--method", required=True, help="Sorting method") args = vars(ap.parse_args())image = cv2.imread(args["image"]) accumEdged = np.zeros(image.shape[:2], dtype="uint8")for chan in cv2.split(image):chan = cv2.medianBlur(chan, 11)edged = cv2.Canny(chan, 50, 200)accumEdged = cv2.bitwise_or(accumEdged, edged)cv2.imshow("Edge Map", accumEdged)(cnts, _) = cv2.findContours(accumEdged.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:5] orig = image.copy()for (i, c) in enumerate(cnts):orig = draw_contour(orig, c, i)cv2.imshow("Unsorted", orig)(cnts, boundingBoxes) = sort_contours(cnts, method=args["method"])for (i, c) in enumerate(cnts):draw_contour(image, c, i)cv2.imshow("Sorted", image) cv2.waitKey(0)?
?
?
?
12、直方圖
直方圖:表示圖像中的像素強(qiáng)度
運(yùn)用cv2.calcHist函數(shù)構(gòu)建直方圖
cv2.calcHist(圖像,通道,掩碼,histSize,范圍)
參數(shù)詳解:
圖像:我們要計(jì)算的直方圖的圖像
通道:索引列表,其中指定要計(jì)算直方圖的通道的索引。
掩碼:提供一個(gè)掩碼,那么只對(duì)被掩蓋的像素計(jì)算一個(gè)直方圖
histSize:計(jì)算直方圖時(shí)要使用的分組數(shù)
范圍:可能的像素值的范圍
#灰度直方圖 from matplotlib import pyplot as plt import argparse import cv2ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="Path to the image") args = vars(ap.parse_args())image = cv2.imread(args["image"])image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) cv2.imshow("Original", image)hist = cv2.calcHist([image], [0], None, [256], [0, 256])plt.figure() plt.title("Grayscale Histogram") plt.xlabel("Bins") plt.ylabel("# of Pixels") plt.plot(hist) plt.xlim([0, 256])hist /= hist.sum()plt.figure() plt.title("Grayscale Histogram (Normalized)") plt.xlabel("Bins") plt.ylabel("% of Pixels") plt.plot(hist) plt.xlim([0, 256]) plt.show() #顏色直方圖 from matplotlib import pyplot as plt import argparse import cv2ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="Path to the image") args = vars(ap.parse_args())image = cv2.imread(args["image"]) cv2.imshow("Original", image)chans = cv2.split(image) colors = ("b", "g", "r") plt.figure() plt.title("'Flattened' Color Histogram") plt.xlabel("Bins") plt.ylabel("# of Pixels")for (chan, color) in zip(chans, colors):hist = cv2.calcHist([chan], [0], None, [256], [0, 256])plt.plot(hist, color = color)plt.xlim([0, 256])fig = plt.figure()ax = fig.add_subplot(131) hist = cv2.calcHist([chans[1], chans[0]], [0, 1], None, [32, 32],[0, 256, 0, 256]) p = ax.imshow(hist, interpolation="nearest") ax.set_title("2D Color Histogram for G and B") plt.colorbar(p)ax = fig.add_subplot(132) hist = cv2.calcHist([chans[1], chans[2]], [0, 1], None, [32, 32],[0, 256, 0, 256]) p = ax.imshow(hist, interpolation="nearest") ax.set_title("2D Color Histogram for G and R") plt.colorbar(p)ax = fig.add_subplot(133) hist = cv2.calcHist([chans[0], chans[2]], [0, 1], None, [32, 32],[0, 256, 0, 256]) p = ax.imshow(hist, interpolation="nearest") ax.set_title("2D Color Histogram for B and R") plt.colorbar(p)print "2D histogram shape: %s, with %d values" % (hist.shape, hist.flatten().shape[0])hist = cv2.calcHist([image], [0, 1, 2],None, [8, 8, 8], [0, 256, 0, 256, 0, 256]) print "3D histogram shape: %s, with %d values" % (hist.shape, hist.flatten().shape[0])plt.show() #直方圖均衡 import argparse import cv2# construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="Path to the image") args = vars(ap.parse_args())# load the image and convert it to grayscale image = cv2.imread(args["image"]) image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# apply histogram equalization to stretch the constrast of our image eq = cv2.equalizeHist(image)# show our images -- notice how the constrast of the second image has # been stretched cv2.imshow("Original", image) cv2.imshow("Histogram Equalization", eq) cv2.waitKey(0) #直方圖和面具 from matplotlib import pyplot as plt import numpy as np import cv2def plot_histogram(image, title, mask=None):chans = cv2.split(image)colors = ("b", "g", "r")plt.figure()plt.title(title)plt.xlabel("Bins")plt.ylabel("# of Pixels")for (chan, color) in zip(chans, colors):hist = cv2.calcHist([chan], [0], mask, [256], [0, 256])plt.plot(hist, color=color)plt.xlim([0, 256])image = cv2.imread("beach.png") cv2.imshow("Original", image) plot_histogram(image, "Histogram for Original Image") mask = np.zeros(image.shape[:2], dtype="uint8") cv2.rectangle(mask, (60, 290), (210, 390), 255, -1) cv2.imshow("Mask", mask)masked = cv2.bitwise_and(image, image, mask=mask) cv2.imshow("Applying the Mask", masked)plot_histogram(image, "Histogram for Masked Image", mask=mask)plt.show()?13、連接分量標(biāo)簽
略
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的计算机视觉-计算机视觉开源库OpenCV基础的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python语言程序设计之Python3
- 下一篇: 计算机视觉开源库OpenCV之图像翻转