OpenCV Python 用HoughLinesP()算法测量距离来确定水位
OpenCV Python measuring distance with HoughLinesP() algorithm to determine water level
我正在尝试使用 OpenCV 和 Python 测量玻璃通道中的水位。我决定在 selected ROI 中使用 HaughLines 并找到所述线的中点,这样我就可以计算出我想要的线之间的差异,并将其与我稍后将获得的设定参考大小相乘在。到目前为止,我发现线条的部分如下所示:
import cv2
import numpy as np
def midpoint(ptA, ptB, ptC, ptD):
return ((ptA + ptC) * 0.5, (ptB + ptD) * 0.5)
img = cv2.imread("b2924.JPG")
img = cv2.resize(img, None, fx=3/10, fy=3/10)
r = cv2.selectROI("main", img, False, False)
cropped = img[r[1]:(r[1]+r[3]), r[0]:(r[0]+r[2])]
cv2.destroyWindow("main")
imgray = cv2.cvtColor(cropped, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(imgray, 35, 75)
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 75, maxLineGap=1000)
midPoint = []
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(cropped, (x1, y1), (x2, y2), (0, 0, 255), 1)
mP = midpoint(x1, y1, x2, y2)
midPoint.append(mP)
midPoint.sort(key = lambda x: x[1])
img[r[1]:(r[1]+r[3]), r[0]:(r[0]+r[2])] = cropped
print(lines)
print(midPoint)
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
根据图像和 ROI,我 select 我发现不一致的结果。图像示例以及我 select ROI 的位置:
请注意,管道底部从管道胶带到达的地方开始。看起来我几乎永远找不到那条确切的线,因为它在基地有多么嘈杂。现在这些没有形态学的阈值似乎给出了更好的结果。我也尝试使用 sobel
导数而不是 canny
但结果更糟。
是否有可能在这种环境下进行精确测量?这是编码问题还是改变我拍照的方式或两者兼而有之?将来我可能需要绘制强湍流期间的水剖面图,我是否应该为此放弃 OpenCV,因为噪音太大了?感谢任何帮助。
我不会投资使用该设置进行任何图像处理。
如果你坚持图像处理(如果你只对几个位置的水平感兴趣,你可能最好使用传统的水平传感器)
在洗手盆后面添加 LED 面板或任何其他类型的均匀背景照明。在水中加入染料以获得一些对比。
摆脱 window 反射。清洁玻璃。
或者使背景变暗,并在水中添加一些东西,使其产生杂散光或荧光。
您还可以添加漂浮在表面上的东西,这些东西可以是反光的,也可以是自发光的。这样你就会得到一个很容易在图像中检测到的明亮的表面水平指示器。
我正在尝试使用 OpenCV 和 Python 测量玻璃通道中的水位。我决定在 selected ROI 中使用 HaughLines 并找到所述线的中点,这样我就可以计算出我想要的线之间的差异,并将其与我稍后将获得的设定参考大小相乘在。到目前为止,我发现线条的部分如下所示:
import cv2
import numpy as np
def midpoint(ptA, ptB, ptC, ptD):
return ((ptA + ptC) * 0.5, (ptB + ptD) * 0.5)
img = cv2.imread("b2924.JPG")
img = cv2.resize(img, None, fx=3/10, fy=3/10)
r = cv2.selectROI("main", img, False, False)
cropped = img[r[1]:(r[1]+r[3]), r[0]:(r[0]+r[2])]
cv2.destroyWindow("main")
imgray = cv2.cvtColor(cropped, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(imgray, 35, 75)
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 75, maxLineGap=1000)
midPoint = []
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(cropped, (x1, y1), (x2, y2), (0, 0, 255), 1)
mP = midpoint(x1, y1, x2, y2)
midPoint.append(mP)
midPoint.sort(key = lambda x: x[1])
img[r[1]:(r[1]+r[3]), r[0]:(r[0]+r[2])] = cropped
print(lines)
print(midPoint)
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
根据图像和 ROI,我 select 我发现不一致的结果。图像示例以及我 select ROI 的位置:
请注意,管道底部从管道胶带到达的地方开始。看起来我几乎永远找不到那条确切的线,因为它在基地有多么嘈杂。现在这些没有形态学的阈值似乎给出了更好的结果。我也尝试使用 sobel
导数而不是 canny
但结果更糟。
是否有可能在这种环境下进行精确测量?这是编码问题还是改变我拍照的方式或两者兼而有之?将来我可能需要绘制强湍流期间的水剖面图,我是否应该为此放弃 OpenCV,因为噪音太大了?感谢任何帮助。
我不会投资使用该设置进行任何图像处理。
如果你坚持图像处理(如果你只对几个位置的水平感兴趣,你可能最好使用传统的水平传感器)
在洗手盆后面添加 LED 面板或任何其他类型的均匀背景照明。在水中加入染料以获得一些对比。 摆脱 window 反射。清洁玻璃。 或者使背景变暗,并在水中添加一些东西,使其产生杂散光或荧光。
您还可以添加漂浮在表面上的东西,这些东西可以是反光的,也可以是自发光的。这样你就会得到一个很容易在图像中检测到的明亮的表面水平指示器。