opencv學習筆記(四)——繪制輪廓、直方圖均衡、模板匹配
繪制輪廓
函數 cv2.?ndContours() 有三個參數,第一個是輸入圖像,第二個是 輪廓檢索模式,第三個是輪廓近似方法。
im = cv2.imread('img/chess.jpg')
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,30,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
#繪制所有輪廓,第一個參數是原始圖像,第二個參數是輪廓,
#第三個參數是輪廓的索引(在繪制獨立輪廓是很有用,當設 置為 -1 時繪制所有輪廓)。
#接下來的參數是輪廓的顏色和厚度。
img = cv2.drawContours(im, contours, -1, (0,255,0), 1)
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
直方圖
通過直方圖你可以對整幅圖像的灰度分布有一個整體的了解。直方圖的 x 軸是灰度值(0 到 255),y軸是圖片中具有同一個灰度值的點的數目。 直方圖其實就是對圖像的另一種解釋。以下圖為例,通過直方圖我們可以對圖像的對比度,亮度,灰度分布等有一個直觀的認識。
首先,了解一下直方圖的相關術語
BINS:上面的直方圖顯示了每個灰度值對應的像素數。如果像素值為 0 到 255,你就需要 256 個數來顯示上面的直方圖。但是,如果你不需要知道 每一個像素值的像素點數目的,而只希望知道兩個像素值之間的像素點數目怎 么辦呢?舉例來說,我們想知道像素值在 0 到 15 之間的像素點的數目,接著 是 16 到 31,....,240 到 255。我們只需要 16 個值來繪制直方圖。你只需要把原來的 256 個值等分成 16 小組,取每組的總和。而這里的每一個小組就被成為 BIN。在 OpenCV 的文檔中用 histSize 表示 BINS。
DIMS:表示我們收集數據的參數數目。在本例中,我們對收集到的數據只考慮一件事:灰度值。所以這里就是 1。
RANGE:就是要統計的灰度值范圍,一般來說為 [0,255],也就是說所有的灰度值
函數 cv2.calcHist 可以幫助我們統計一幅圖像的直方圖。
img = cv2.imread('img/cat1.jpg',0)
hist = cv2.calcHist([img],[0],None,[256],[0,256])
'''
1. images: 原圖像(圖像格式為 uint8 或 ?oat32)。當傳入函數時應該 用中括號 [] 括起來,例如:[img]。
2. channels: 同樣需要用中括號括起來,它會告訴函數我們要統計那幅圖 像的直方圖。如果輸入圖像是灰度圖,
它的值就是 [0];如果是彩色圖像 的話,傳入的參數可以是 [0],[1],[2] 它們分別對應著通道 B,G,R。
3. mask: 掩模圖像。要統計整幅圖像的直方圖就把它設為 None。但是如 果你想統計圖像某一部分的直方圖的話,
你就需要制作一個掩模圖像,并 使用它。(后邊有例子)
4. histSize:BIN 的數目。也應該用中括號括起來,例如:[256]。
5. ranges: 像素值范圍,通常為 [0,256]
'''
img = cv2.imread('img/cat1.jpg',0)
plt.hist(img.ravel(),256,[0,256]);
plt.show()
或者你可以使用 matplotlib 的繪圖功能,這在同時繪制多通道(BGR)的直方圖
img = cv2.imread('img/cat1.jpg')
color = ('b','g','r')
#對一個列表或數組既要遍歷索引又要遍歷元素時使用內置enumerrate函數會有更加直接,
#enumerate會將數組或列表組成一個索引序列。使我們再獲取索引和索引內容的時候更加方便
for i,col in enumerate(color):
histr = cv2.calcHist([img],[i],None,[256],[0,256])
plt.plot(histr,color = col)
plt.xlim([0,256])
plt.show()
直方圖均衡化
想象一下如果一副圖像中的大多是像素點的像素值都集中在一個像素值范 圍之內會怎樣呢?例如,如果一幅圖片整體很亮,那所有的像素值應該都會很高。但是一副高質量的圖像的像素值分布應該很廣泛。所以你應該把它的直方圖做一個橫向拉伸(如下圖),這就是直方圖均衡化要做的事情。通常情況下這 種操作會改善圖像的對比度。
OpenCV 中的直方圖均衡化函數為 cv2.equalizeHist()。這個函數的輸入圖片是一副灰度圖像,輸出結果是直方圖均衡化之后的圖像。
img = cv2.imread('img/dog.JPEG',0)
equ = cv2.equalizeHist(img)
res = np.hstack((img,equ))
cv2.imwrite('res.png',res)
我們在上邊做的直方圖均衡化會改變整個圖像的對比度,但是在很多情況下,這樣做的效果并不好,因為會導致部分區域亮度過高而丟失信息。造成這種結果的根本原因在于這幅圖像的直方圖并不是集中在某一個區域(試著畫出它的直方圖,你就明白了)。
為了解決這個問題,我們需要使用自適應的直方圖均衡化。這種情況下,整幅圖像會被分成很多小塊,這些小塊被稱為“tiles”(在 OpenCV 中 tiles 的 大小默認是 8x8),然后再對每一個小塊分別進行直方圖均衡化(跟前面類似)。 所以在每一個的區域中,直方圖會集中在某一個小的區域中(除非有噪聲干 擾)。如果有噪聲的話,噪聲會被放大。為了避免這種情況的出現要使用對比度限制。對于每個小塊來說,如果直方圖中的 bin 超過對比度的上限的話,就把 其中的像素點均勻分散到其他 bins 中,然后在進行直方圖均衡化。最后,為了去除每一個小塊之間“人造的”(由于算法造成)邊界,再使用雙線性差值,對小塊進行縫合。
img = cv2.imread('img/dog.JPEG',0)
clahe = cv2.createCLAHE(clipLimit=4.0, tileGridSize=(8,8)) #clipLimit顏色對比度的閾值
cl1 = clahe.apply(img)
cv2.imshow("img", cl1)
cv2.waitKey(0)
cv2.destroyAllWindows()
模板匹配
模板匹配是用來在一副大圖中搜尋查找模版圖像位置的方法。OpenCV 為 我們提供了函數:cv2.matchTemplate()。和 2D 卷積一樣,它也是用模 板圖像在輸入圖像(大圖)上滑動,并在每一個位置對模板圖像和與其對應的 輸入圖像的子區域進行比較。OpenCV 提供了幾種不同的比較方法(細節請看 文檔)。返回的結果是一個灰度圖像,每一個像素值表示了此區域與模板的匹配 程度。
如果輸入圖像的大小是(WxH),模板的大小是(wxh),輸出的結果 的大小就是(W-w+1,H-h+1)。當你得到這幅圖之后,就可以使用函數 cv2.minMaxLoc() 來找到其中的最小值和最大值的位置了。第一個值為矩形左上角的點(位置),(w,h)為 moban 模板矩形的寬和高。這個矩形就是找到的模板區域了。注意:如果你使用的比較方法是 cv2.TM_SQDIFF,最小值對應的位置才是匹 配的區域。
img = cv2.imread('img/cat1.jpg',0)
img2 = img.copy()
template = cv2.imread('img/cathead.png',0)
w, h = template.shape[::-1]
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR', 'cv2.TM_CCORR_NORMED',
'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
for meth in methods:
img = img2.copy()
method = eval(meth)
res = cv2.matchTemplate(img,template,method)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(img,top_left, bottom_right, 255, 2)
plt.subplot(121),plt.imshow(res,cmap = 'gray')
plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img,cmap = 'gray')
plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
plt.suptitle(meth)
plt.show()
智能推薦
opencv學習筆記二十:模板匹配
模板匹配就是拿模板去遍歷圖像,在遍歷的每個位置計算結果,即匹配程度,opencv中 提供了 6 種計算方法: 差值平方和匹配 CV_TM_SQDIFF 標準化差值平方和匹配 CV_TM_SQDIFF_NORMED 相關匹配 CV_TM_CCORR 標準相關匹配 CV_TM_CCORR_NORMED 相關匹配 CV_TM_CCOEFF 標準相關匹配 CV_TM_CCOEFF_NORMED ...
【opencv學習筆記】028之模板匹配
目錄 一、前言 二、模板匹配 1、模板匹配是個啥 2、常用匹配算法 1.平方差匹配-CV_TM_SQDIFF 2.標準平方差匹配-CV_TM_SQDIFF_NORMED 3.相關匹配-CV_TM_CCORR 4.標準相關匹配-CV_TM_CCORR_NORMED 5.相關匹配-CV_TM_CCOEFF 6.標準相關匹配-CV_TM_CCOEFF_NORMED 3、API 4、代碼展示 5、執行結果...
openCV學習筆記十五:模板匹配
1.模版匹配——matchTemplate() 2.實現了幾個小應用:圖像單目標模板匹配、視頻單目標模板匹配、 首先來了解三個函數: minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() ); 函數中的參數有: result: 匹配結果矩陣 &minVal 和 &am...
猜你喜歡
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...