本篇將介紹如下要點:html
首先須要導入必要的庫、解析參數python
#導入必要的軟件包,包括Python附帶的命令行參數解析包argparse import argparse import imutils import cv2 #構造參數解析器並解析參數 ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="path to input image") args = vars(ap.parse_args())
# 加載圖像 (路徑包含在命令行參數中)而且顯示 image = cv2.imread(args["image"]) cv2.imshow("Image", image) cv2.waitKey(0) # 轉換圖像爲灰度圖像,須要image和cv2.COLOR_BGR2GRAY標誌 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) cv2.imshow("Gray", gray) cv2.waitKey(0)
邊緣檢測對於查找圖像中對象的邊界頗有用,多用於圖像分割。算法
# 應用邊緣檢測找到圖像中目標物體的輪廓 edged = cv2.Canny(gray, 30, 150) cv2.imshow("Edged", edged) cv2.waitKey(0)
使用流行的Canny算法(由John F. Canny在1986年開發),咱們能夠找到圖像中的邊緣。
cv2.Canny函數須要三個參數:app
不一樣的最小閾值和最大閾值將返回不一樣的邊緣圖
less
圖像閾值化是圖像處理的重要中間步驟,閾值處理能夠幫助咱們去除較亮或較暗的圖像區域和輪廓。
經過反覆試驗(以及經驗)對如下代碼進行了調整,使其適用於本示例:函數
# 全部灰度值<225的像素點設置爲255(白色)-俄羅斯方塊 # 灰度值>=225且<=255的像素點設置爲0(黑色)——背景 thresh = cv2.threshold(gray, 225, 255, cv2.THRESH_BINARY_INV)[1] cv2.imshow("Thresh", thresh) cv2.waitKey(0)
有關cv2.threshold函數的更多信息請參考opencv官方文檔。
使用二值化圖像從背景中分割前景對於找到輪廓相當重要。
oop
# 在圖像中找到前景物體的輪廓 cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) output = image.copy() # 循環繪製輪廓 for c in cnts: # 以紫色線條繪製輪廓 # 一次顯示一個物體的輪廓 cv2.drawContours(output, [c], -1, (240, 0, 159), 3) cv2.imshow("Contours", output) cv2.waitKey(0)
使用cv2.findContours以檢測圖像中的輪廓,圖像使用的是二值化圖像,注意函數的參數可是問題簡單化就是找到前景(白色)像素點。
使用以前文章中的知識,在圖像上覆蓋一些文本:ui
# 註明紫色輪廓的個數 text = "I found {} objects!".format(len(cnts)) cv2.putText(output, text, (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (240, 0, 159), 2) cv2.imshow("Contours", output) cv2.waitKey(0)
變量text是包含形狀輪廓數量的字符串,計算此圖像中的對象總數就是檢查輪廓列表的長度len(cnts)
spa
侵蝕和膨脹一般用於減小二進制圖像中的噪聲(閾值的反作用)。
(1)爲了減小前景對象的尺寸,咱們能夠經過屢次迭代來腐蝕掉像素:命令行
#經過腐蝕減少前景物體的尺寸,利用cv2.erode將輪廓尺寸減少5 mask = thresh.copy() mask = cv2.erode(mask, None, iterations=5) cv2.imshow("Eroded", mask) cv2.waitKey(0)
使用OpenCV腐蝕輪廓,有效地縮小輪廓或使它們在通過足夠的迭代後徹底消失,這對於去除二值化圖像中的噪聲點一般頗有用。
(2)要擴大前景對象的尺寸,只需使用cv2.dilate:
# 膨脹能夠擴大前景對象的尺寸 mask = thresh.copy() mask = cv2.dilate(mask, None, iterations=5) cv2.imshow("Dilated", mask) cv2.waitKey(0)
在圖像處理中,若是須要鏈接附近的輪廓,則能夠對圖像進行放大。圖中顯示的是經過五次迭代對輪廓進行擴張的結果,但並未使兩個輪廓變爲一個。
稱爲遮罩是由於它們將隱藏咱們不關心的圖像區域,好比使用二值化圖像將原始圖像覆蓋,將獲得如下結果:
背景如今是黑色,前景由彩色像素組成——一些像素點被二值化,突出俄羅斯方塊區域
#咱們可能要應用的典型操做是遮蓋圖像某部分 #對輸入圖像按位與 # regions mask = thresh.copy() output = cv2.bitwise_and(image, image, mask=mask) cv2.imshow("Output", output) cv2.waitKey(0)
終端輸入:
python opencv_tutorial_02.py --image tetris_blocks.png
參數標誌是--image,而且image參數是tetris_blocks.png——目錄中相關文件的路徑。
最後貼上源代碼:
# USAGE # python opencv_tutorial_02.py --image tetris_blocks.png # import the necessary packages import argparse import imutils import cv2 # construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="path to input image") args = vars(ap.parse_args()) # load the input image (whose path was supplied via command line # argument) and display the image to our screen image = cv2.imread(args["image"]) cv2.imshow("Image", image) cv2.waitKey(0) # convert the image to grayscale gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) cv2.imshow("Gray", gray) cv2.waitKey(0) # applying edge detection we can find the outlines of objects in # images edged = cv2.Canny(gray, 30, 150) cv2.imshow("Edged", edged) cv2.waitKey(0) # threshold the image by setting all pixel values less than 225 # to 255 (white; foreground) and all pixel values >= 225 to 255 # (black; background), thereby segmenting the image thresh = cv2.threshold(gray, 225, 255, cv2.THRESH_BINARY_INV)[1] cv2.imshow("Thresh", thresh) cv2.waitKey(0) # find contours (i.e., outlines) of the foreground objects in the # thresholded image cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) output = image.copy() # loop over the contours for c in cnts: # draw each contour on the output image with a 3px thick purple # outline, then display the output contours one at a time cv2.drawContours(output, [c], -1, (240, 0, 159), 3) cv2.imshow("Contours", output) cv2.waitKey(0) # draw the total number of contours found in purple text = "I found {} objects!".format(len(cnts)) cv2.putText(output, text, (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (240, 0, 159), 2) cv2.imshow("Contours", output) cv2.waitKey(0) # we apply erosions to reduce the size of foreground objects mask = thresh.copy() mask = cv2.erode(mask, None, iterations=5) cv2.imshow("Eroded", mask) cv2.waitKey(0) # similarly, dilations can increase the size of the ground objects mask = thresh.copy() mask = cv2.dilate(mask, None, iterations=5) cv2.imshow("Dilated", mask) cv2.waitKey(0) # a typical operation we may want to apply is to take our mask and # apply a bitwise AND to our input image, keeping only the masked # regions mask = thresh.copy() output = cv2.bitwise_and(image, image, mask=mask) cv2.imshow("Output", output) cv2.waitKey(0)