python - 找到凹弯曲形状斑点的宽度和高度
问题描述
我一直在为计算像这样的图形的宽度和高度测量值这个问题而摸不着头脑。主要的挑战是我不能使用 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)`
解决方案
这是一个 OpenCV 解决方案。主要思想是
- 将图像转换为灰度和反转图像
- 查找 blob 的轮廓和质心
- 使用 Numpy 切片获取所有行/列像素
- 计算非零像素以确定宽度/高度
我们将图像转换为灰度并反转它。这是我们将计算像素的图像,因为所需的 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)
推荐阅读
- iis - MSDEPLOY 得到 ERROR_USER_UNAUTHORIZED。我在哪里可以找到原因?
- .htaccess - htaccess URL 重写 domain.com.php 页面格式?
- android - 如何为 API 级别 20 以上的 Android 设备请求 AudioFocus?
- java - 你怎么写这个 s = ( (n % 2 ) == 0 ? "0" : "1") +s; 作为 if-else 语句?
- terminal - 为什么每次我想在终端中运行命令脚本时都必须运行'source .zsh'?
- ios - SwiftUI 视图内容布局意外弹出/跳转出现?
- c# - 是否有类似外部自定义模型绑定器的东西?
- c# - System.ServiceModel.Security.SecurityNegotiationException:无法为具有权限“dev.xyz.com”的 SSL/TLS 建立安全通道
- javascript - 在本机反应中将数据从子组件传递到父组件?
- r - ShinydashboardPlus 中默认打开右侧边栏