我一直在为计算这样一个图形的宽度和高度尺寸的问题而problem之以鼻。主要的挑战是我不能使用miBoundingrectangle,也找不到从内部进行边界的方法,无论哪种方式,我都会丢失一些用于高度和宽度测量的像素。
样本输入:
样本输出:
是否有任何防故障方法来进行精确的尺寸测量?
以下是我正在尝试找到内部边界最大矩形的解决方案。
_,contour2,_=cv2.findContours(im,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_NONE)
for c in contour2:
area=cv2.contourArea(c)
if area ==25224.0:
print(area)
n = np.squeeze(contour2[0])
x = sorted(n, key=lambda a:a[0])
left = x[0]
right = x[-1]
print("",left,right)
y= sorted(n, key=lambda a:a[1])
top = y[0]
bottom = y[-1]
cv2.drawContours(im,[c],-1,(128,128,128),2)
cv2.circle(im, (left[0],left[1]), 4, (128,128,128), 8)
cv2.circle(im, (right[0],right[1]), 4, (128,128,128), 8)
cv2.circle(im, (top[0],top[1]), 4, (128,128,128), 8)
cv2.circle(im, (bottom[0],bottom[1]), 4, (128,128,128), 8)
roi_w = int(np.sqrt((top[0]-right[0])*(top[0]-right[0])(top[1]-right[1])*(top[1]-right[1])))
roi_h = int(np.sqrt((top[0]-left[0])*(top[0]-left[0])+(top[1]-left[1])*(top[1]-left[1])))
pts1 = np.float32([top,right,left])
new_top = top
new_right = [top[0] + roi_w, top[1]]
new_left = [top[0], top[1] + roi_h]
pts2 = np.float32([new_top,new_right,new_left])
cv2.imshow("threshed", im)`
答案 0 :(得分:4)
这是OpenCV解决方案。主要思想是
我们将图像转换为灰度并反转。由于期望的ROI为白色,因此这是我们要依靠像素的图像。从这里,我们使用cv2.moments()
找到斑点的轮廓和中心坐标。这给了我们质心(即对象的中心(x,y)坐标)
M = cv2.moments(c)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
接下来,我们使用Numpy切片来获取所有行和列像素。我们使用cv2.countNonZero()
查找这样的行/列的宽度/高度
row_pixels = cv2.countNonZero(gray[cY][:])
column_pixels = cv2.countNonZero(gray[:, cX])
这是一个可视化
这是结果
第150行
第354列
import cv2
import numpy as np
image = cv2.imread('1.png')
inverted = 255 - image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = 255 - gray
cnts = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
M = cv2.moments(c)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
cv2.circle(inverted, (cX, cY), 5, (36, 255, 12), -1)
inverted[cY][:] = (36, 255, 12)
inverted[:, cX] = (36, 255, 12)
row_pixels = cv2.countNonZero(gray[cY][:])
column_pixels = cv2.countNonZero(gray[:, cX])
print('row', row_pixels)
print('column', column_pixels)
cv2.imshow('inverted', inverted)
cv2.imwrite('inverted.png', image)
cv2.waitKey(0)
答案 1 :(得分:2)
这是Imagemagick的解决方案。但是该概念将为您提供如何继续使用OpenCV的线索。它不是您想要的尺寸。但是我能想到的最接近的方式。基本上,它是最大内部边界框。也许在OpenCV中有类似的东西。
从外部到内部围绕图像的每个边缘进行迭代,直到每个剩余的边缘完全变成黑色,没有白色(或接近白色)。
输入:
convert img.png -threshold 0 -define trim:percent-background=0% -trim +repage -format "%wx%h" +write info: result.png
returns: widthxheight => 144x317
添加:
这是在OpenCV中应该易于实现的另一种解决方案。
修剪以获取最小外部边界框。提取中间的行和列,两端可能有一些白色。然后在周围涂抹白色。然后再次修剪所有白色,这样就剩下一个黑色的行和一列而没有白色。然后获得单个黑色行和单个黑色列的尺寸。
width=`convert img.png -threshold 0 -trim +repage -gravity center -crop x1+0+0 +repage -bordercolor white -border 1x1 -trim +repage -format "%w" info:`
height=`convert img.png -threshold 0 -trim +repage -gravity center -crop 1x+0+0 +repage -bordercolor white -border 1x1 -trim +repage -format "%h" info:`
echo "width=$width; height=$height;"
returns: => width=145; height=352;