簡體   English   中英

計算圖像中不規則形狀的對象覆蓋的面積

[英]Calculating the area covered by the objects of irregular shapes in an image

我正在一個項目中,根據圖像中的小麥峰值估算小麥產量。 在使用Faster-RCNN和基於顏色的分割檢測尖峰之后,以下是所得圖像,其中圖像中只有尖峰。

僅具有小麥尖峰的圖像

現在,我的目標是使用python估計圖像中尖峰產生的產量。 為此,我們可能必須計算由多邊形形狀的對象覆蓋的面積,或者可能必須圍繞像素值進行計算才能計算出面積。 但是我不知道我們該怎么做。 請讓我知道是否有人可以解決。 謝謝

通過創建二進制蒙版可以找到非黑色的圖像像素區域。 以像素為單位的面積等於蒙版中白色像素的總數。 一種獲取方法是計算圖像中白色像素的比例。 白色像素的數量將是圖像的分數*寬度*高度。 該分數只是圖像的平均值除以最大可能的灰度等級(255)。 所以

白色像素的像素面積=(平均值/ 255) 寬度高度

因此,獲得二進制掩膜圖像的分數平均值(平均值/ 255)(通過將閾值設置為0)。 平均值的結果將是一個單一值。 然后將其乘以圖像的寬度,再乘以圖像的高度。 該結果將等於蒙版中白色像素的總數,從而等於圖像中非黑色(即彩色)的像素總數。 白色像素數是圖像中非黑色像素的像素面積。

輸入:

在此處輸入圖片說明

import cv2
import numpy as np
img = cv2.imread('img.jpg')
height = img.shape[0]
width = img.shape[1]
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)
cv2.imshow("Mask", thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()
ave = cv2.mean(thresh)[0]/255
print(ave)
0.310184375
area = ave*height*width
print(area)
198518.0

請注意,這是非黑色像素區域。 您的某些矩形內部有黑色。 因此,這不是矩形的區域。 在隔離矩形以獲取矩形區域之前,您將確保圖像沒有黑色像素。

加成

Mark Setchell建議的一種更簡單的方法是簡單地計算閾值圖像中非零像素的數量。 它計算出與上述相同的數字。

import cv2
import numpy as np
img = cv2.imread('img.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)
cv2.imshow("Mask", thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()
area2 = cv2.countNonZero(thresh)
print(area2)
198518

補充2

如果您知道與圖像所覆蓋區域相對應的地面面積或尺寸(以米為單位,根據您的評論,一邊為0.8 m),那么與非零像素計數相對應的地面面積將為:

area on ground for nonzero pixels = count * 0.8 * 0.8 / (width * height)


其中寬度和高度是圖像的像素尺寸。

import cv2
import numpy as np
img = cv2.imread('img.jpg')
height = img.shape[0]
width = img.shape[1]
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)
cv2.imshow("Mask", thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()
count = cv2.countNonZero(thresh)
area = count*0.8*0.8/(width*height)
print(area)
0.19851800000000003


這樣的結果是0.198518平方米

希望這可以幫助😉

  1. 加載灰度圖像(0[Black] - 255[White])
  2. 提取一定水平以上的像素。 我有超過60使用cv2.threshold
  3. 使用cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)使用最小的內核(3,3)填充小的白色斑點
  4. 從閾值圖像中提取輪廓
  5. 以相反的順序遍歷每個輪廓(從右上到右下角)
  6. 遍歷每個輪廓時,計算其屬性

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('RIUXF.jpg',0)
hist = cv2.calcHist([img],[0],None,[256],[0,256])

# Area occupied by black region
black_area = np.true_divide(hist[0],np.prod(img.shape))[0]*100

# extract no black parts
thresh = cv2.threshold(img,60,255,cv2.THRESH_BINARY)[1]
kernel = np.ones((3,3),np.uint8)

# fill in the small white spots
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

# extract the contours
contours = cv2.findContours(opening, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0]

blank_image = np.zeros((img.shape),np.uint8)
image_area = np.prod(img.shape)

# iterate through the contours detected from right top corner
for i,c in enumerate(contours[::-1]):

    # turn blank_image black
    blank_image *= 0

    # draw filled contour
    cv2.drawContours(blank_image, [c], 0, (255), thickness=cv2.FILLED)

    contour_area = cv2.contourArea(c)

    # percentage of area contour
    contour_area_pc = np.true_divide(int(contour_area),image_area)*100 if int(contour_area) > 1  else 0 
    text = ' '.join(['Contour:',str(i),'Area:',str(round(contour_area,2)),'Percentage Area:',str(round(contour_area_pc,2))])
    cv2.putText(blank_image,text,(10,60), cv2.FONT_HERSHEY_SIMPLEX, 1,(255),2,cv2.LINE_AA)

    plt.imshow(blank_image, cmap = 'gray', interpolation = 'bicubic')
    plt.xticks([]), plt.yticks([])  # to hide tick values on X and Y axis
    plt.show()

樣品輸出

在此處輸入圖片說明

PS:我懷疑cv2區域計算是否正確🤔

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM