天天看點

基于opencv實作對圖檔中的物體計數1. 基本思路2.代碼3.局限性

目錄

  • 1. 基本思路
  • 2.代碼
  • 3.局限性

1. 基本思路

1. 保證圖檔背景盡量為純黑或純白

為了數量檢測的友善,将垃圾的背景設定為純色,最好是純黑色或純白色,一會解釋原因。

基于opencv實作對圖檔中的物體計數1. 基本思路2.代碼3.局限性

2. 将RGB圖檔轉為灰階圖

基于opencv實作對圖檔中的物體計數1. 基本思路2.代碼3.局限性

3. opencv找到能将灰階值最大程度分開的門檻值ret

opencv的算法自動找到最合适的門檻值ret,ret能将灰階圖每個像素的灰階值最大限度的區分開。灰階圖每個像素的灰階值為0(純黑)到255(純白),上面的灰階圖中像素灰階值的分布如下所示。

基于opencv實作對圖檔中的物體計數1. 基本思路2.代碼3.局限性

可以看到opencv自動找到ret=92。

這裡來說明兩個問題:

(1)為什麼要轉為灰階圖?

因為彩色圖有RGB三個次元,而灰階圖隻有0(純黑)-255(純白)這一個次元,便于處理。

(2)為什麼要保證背景盡量為純黑或純白?

因為在第三步找門檻值ret時,要把灰階值的分布圖最大程度的分開。背景顔色所占像素很多,如果背景為别的顔色,轉為灰階值會位于分布圖的中間,就會影響找到的門檻值ret。(我們可以看到,在上面的分布圖中大多數灰階值接近0,這是因為背景接近黑色,轉換為灰階值會更接近0)

4. 二值化處理

灰階值小于ret的像素置為0(黑色),大于ret的像素值為255(白色),将上面的灰階圖轉換為黑白圖,如下所示:

基于opencv實作對圖檔中的物體計數1. 基本思路2.代碼3.局限性

5. 計算白色區域的個數

使用opencv算法對每個不相鄰的白色區域像素值進行統計,同時過濾像素值較小的白色區域。(如某個白色區域隻有20個像素值,則不大可能是一個物品,排除)對像素量超過1000的白色區域計數,即可得到圖檔中物體的數量。

還可以畫出連通域:

基于opencv實作對圖檔中的物體計數1. 基本思路2.代碼3.局限性

2.代碼

import cv2

# # 計算面積 去除面積小的 連通域
def Filter(contours):
    sum = 0
    a = []
    for i,area in enumerate(contours):
        if cv2.contourArea(area)>800:  
            a.append(contours[i])
            sum+=1
    return sum, a

if __name__ == '__main__':
    frame = cv2.imread("E:\\GarbageClassification\\1.png")   
    gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) #将圖檔變為灰階圖檔
    ret2, thresh2 = cv2.threshold(gray,0,255,cv2.THRESH_OTSU)# 算法自動找出合适門檻值ret2,将灰階圖轉換為黑白圖,thresh2為傳回的黑白圖
    contours,hirearchy=cv2.findContours(thresh2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 找出連通域
    sum, contours_1 = Filter(contours)
    img1=cv2.drawContours(frame,contours_1,-1,(0,0,255),3)

    # 所有操作結束後進行釋放
    cv2.imshow("img1",gray)
    cv2.imshow("img2",thresh2)
    cv2.imshow("img3",img1)
    print(sum)
    if cv2.waitKey():
        cv2.destroyAllWindows()


           

3.局限性

這個思路很簡單粗暴,但也存在一些局限性:

(1)對背景有要求,背景不能太亂,對環境較為敏感,盡量保證物品和背景顔色差别較大;

(2)物品最好不要反光,否則會檢測不準;

(3)無法處理物品有重疊的情況,如果兩個橙子挨在一起,就會檢測成一個。

繼續閱讀