繁体   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