如何用Python cv2包测量中心角?

问题描述 投票:0回答:1

我们的团队建立了一套视觉系统,包括一个摄像头、一个显微镜和一个可调谐的镜头,来观察一个锥体的内表面。

从视觉上看,一个锥体的摄像头可以拍摄12张图像,每张图像覆盖30度。

现在我们已经收集了很多样本图像,想确保每个 "扇形"(如下图所示)至少是30度。

有没有什么办法 Python,与 cv2 或其他包,来测量这个中心角。谢谢,我们的团队建立了视觉系统

enter image description here

python opencv angle cv2
1个回答
2
投票

下面是PythonOpenCV中的一种方法。

  • 阅读图片
  • 转换为灰色
  • 阈值
  • 利用形态学的开合来平滑和填充边界。
  • 应用Canny边缘提取
  • 将图像分为上边和下边,将对边涂黑。
  • 将线条与上、下边缘贴合
  • 计算每条边的角度
  • 计算两个角的差值
  • 在输入上画线
  • 保存结果

输入。

enter image description here

import cv2
import numpy as np
import math

# read image
img = cv2.imread('cone_shape.jpg')

# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# threshold
thresh = cv2.threshold(gray,11,255,cv2.THRESH_BINARY)[1]

# apply open then close to smooth boundary
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (13,13))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = np.ones((33,33), np.uint8)
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)

# apply canny edge detection
edges = cv2.Canny(morph, 150, 200)
hh, ww = edges.shape
hh2 = hh // 2

# split edge image in half vertically and blacken opposite half
top_edge = edges.copy()
top_edge[hh2:hh, 0:ww] = 0
bottom_edge = edges.copy()
bottom_edge[0:hh2, 0:ww] = 0

# get coordinates of white pixels in top and bottom
# note: need to transpose y,x in numpy to x,y for opencv
top_white_pts = np.argwhere(top_edge.transpose()==255)
bottom_white_pts = np.argwhere(bottom_edge.transpose()==255)

# fit lines to white pixels
# (x,y) is point on line, (vx,vy) is unit vector along line
(vx1,vy1,x1,y1) = cv2.fitLine(top_white_pts, cv2.DIST_L2, 0, 0.01, 0.01)
(vx2,vy2,x2,y2) = cv2.fitLine(bottom_white_pts, cv2.DIST_L2, 0, 0.01, 0.01)

# compute angle for vectors vx,vy
top_angle = (180/math.pi)*math.atan(vy1/vx1)
bottom_angle = (180/math.pi)*math.atan(vy2/vx2)
print(top_angle, bottom_angle)

# cone angle is the difference
cone_angle = math.fabs(top_angle - bottom_angle)
print(cone_angle)

# draw lines on input
lines = img.copy()
p1x1 = int(x1-1000*vx1)
p1y1 = int(y1-1000*vy1)
p1x2 = int(x1+1000*vx1)
p1y2 = int(y1+1000*vy1)
cv2.line(lines, (p1x1,p1y1), (p1x2,p1y2), (0, 0, 255), 1)
p2x1 = int(x2-1000*vx2)
p2y1 = int(y2-1000*vy2)
p2x2 = int(x2+1000*vx2)
p2y2 = int(y2+1000*vy2)
cv2.line(lines, (p2x1,p2y1), (p2x2,p2y2), (0, 0, 255), 1)

# save resulting images
cv2.imwrite('cone_shape_thresh.jpg',thresh)
cv2.imwrite('cone_shape_morph.jpg',morph)
cv2.imwrite('cone_shape_edges.jpg',edges)
cv2.imwrite('cone_shape_lines.jpg',lines)

# show thresh and result    
cv2.imshow("thresh", thresh)
cv2.imshow("morph", morph)
cv2.imshow("edges", edges)
cv2.imshow("top edge", top_edge)
cv2.imshow("bottom edge", bottom_edge)
cv2.imshow("lines", lines)
cv2.waitKey(0)
cv2.destroyAllWindows()

阈值的图像。

enter image description here

形态学处理的图像:

enter image description here

边缘图像:

enter image description here

输入上的线条。

enter image description here

锥体角度(度):42.03975696357633

42.03975696357633


1
投票

这听起来是可能的。你需要进行一些预处理和过滤,以找出有效的方法,而且可能需要进行一些调整。

有三种方法可以工作。

1.)

基本的想法是以某种方式得到两条线并测量它们之间的角度。

  • 定义一个阈值来定义外部黑色区域(出中心角),并将所有低于它的值设置为零。

  • 这也会将中心角内的一些模糊条纹设置为零,所以我们要尝试将它们 "治愈 "掉。这可以通过使用 形态转换. 你可以读到他们 此处此处.

  • 你可以尝试操作 闭幕但我不知道它是否能修复条纹。一般来说,它可以修复点状或划痕。这个答案 似乎表明,它应该在线条上工作。

  • 也许这时再应用一些高斯模糊和到阈值的东西。然后尝试使用一些边缘或线条检测。

基本上是试错,你得看看什么是有效的。

2.)

  • 另一个可行的办法是尝试使用弧线-------------------------------------------。enter code here如划痕,甚至可能加强它们,并使用。霍夫圆环变换. 我想它也能检测到弧线。

  • 试试吧,看看函数返回什么。在最好的情况下,有几个圆弧,你可以用它来估计中心角。

  • 电弧检测的几种方法 在StackOverflow或 此处.

  • 我不确定你的所有图像是否都是如此,但上面那张看起来像是有一些细长的、绿色和粉色的弧线,似乎沿着中心角度一直延伸。你可以用它来过滤这种颜色,然后把它做成灰度。

  • 这个问题 可能会有帮助。

3.)

  • 应用边缘过滤器,如Canny。skimage.feature.canny

  • 尝试几个sigmas,并在你的问题中发布图像,然后我们可以尝试思考如何继续。

  • 可以做的是计算所有属于边缘的点周围的凸壳。然后从凸壳中得到形成中心角的两条线。

© www.soinside.com 2019 - 2024. All rights reserved.