我每 10 分钟拍摄一次放在太阳前面的 10 厘米钉子阴影的图像。然而,我在清晨和傍晚时面临着挑战,当时阴影变得微弱而苍白,使我的算法很难检测到它们。这是我试图检测的微弱阴影的示例:
当阴影颜色丰富或强烈时,我的算法成功检测到它。然而,在阴影较弱的情况下,它无法识别该线。我需要获取线的顶部和底部的坐标来计算其长度。
我的代码是:
import time
import numpy as np
import cv2
from math import atan, sqrt, degrees
def captureImage():
print('Capturing image')
videoCaptureObject = cv2.VideoCapture(1)
result = True
while(result):
ret, frame = videoCaptureObject.read()
cv2.imwrite("Newpicture.jpg", frame)
result = False
videoCaptureObject.release()
return frame
def processImage(im):
print('Processing image')
image = im
# Convert image to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Apply Gaussian blur to reduce noise
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# Apply a median filter to enhance the line
blurred = cv2.medianBlur(blurred, 5)
# Convert grayscale image to binary using a manually adjusted threshold
_, thresh = cv2.threshold(blurred, 100, 255, cv2.THRESH_BINARY_INV)
# Apply edge detection
edges = cv2.Canny(thresh, 50, 150)
# Find contours in the edge-detected image
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
# Get the largest contour (assuming it's the line)
c = max(contours, key=cv2.contourArea)
# Get the extreme points of the contour (line)
x1, y1 = c[c[:, :, 0].argmin()][0]
x2, y2 = c[c[:, :, 0].argmax()][0]
# Calculate the length of the line
length = sqrt((x2 - x1)**2 + (y2 - y1)**2)
# Print the coordinates and length
print(f"Top: ({x1}, {y1}), Bottom: ({x2}, {y2}), Length: {length}")
# Repeat the process 100 times with a 3-minute interval
for i in range(100):
captureImage()
time.sleep(180) # 3 minutes in seconds
processImage(captureImage())
我调整了高斯模糊和边缘检测的参数,但这些更改并没有解决问题。我什至购买了更高质量的相机,但问题仍然存在。
以下是可以用来改进微弱阴影检测的技术:
1. 增强预处理:
-
自适应阈值化:
与其使用全局阈值,不如使用自适应阈值化,如
cv2.adaptiveThreshold
,它会根据图像中局部区域的光线条件设置阈值。这在照明不均匀时很有帮助。 -
直方图均衡化:
通过扩展图像的直方图,可以增强对比度,从而使阴影更加突出。尝试使用
cv2.equalizeHist
。 -
白平衡:
确保图像色彩平衡良好。白平衡不佳会导致阴影难以检测。可以使用
cv2.cvtColor
及其各种色彩空间转换标志来实现此目的。
2. 特征增强:
-
定向梯度直方图 (HOG):
HOG 描述符非常适合检测图像中的边缘和梯度,这对于查找阴影边界非常有用。可以使用
skimage.feature.hog
计算 HOG 特征。 - 高斯差分 (DoG): DoG 是一种带通滤波器,可以突出显示边缘并减少噪声。它可以通过连续应用具有不同标准差的高斯模糊,然后减去结果来实现。
3. 基于模型的检测:
- 训练分类器: 使用阴影和非阴影区域的标记图像数据集来训练机器学习分类器(例如,支持向量机或卷积神经网络)。训练后的分类器可以直接预测图像中的阴影区域。
-
线检测霍夫变换:
霍夫变换非常适合检测图像中的线条,即使它们是部分的或微弱的。可以使用
cv2.HoughLinesP
来实现此目的。
4. 代码改进:
- 将 Canny 边缘检测应用于模糊图像: 在的代码中,正在模糊图像,然后应用中值滤波器,然后应用 Canny 边缘检测。尝试在应用 Canny 边缘检测 之后 应用中值滤波器或去除中值滤波器。
-
使用
cv2.minAreaRect
获取线方向: 与其使用轮廓的最左和最右点来确定线的长度,不如使用cv2.minAreaRect
获取包围检测到的轮廓的旋转边界框。这将提供更准确的长度估计,即使线条不完全垂直。
5. 硬件考虑因素:
- 偏光镜: 在相机镜头上使用偏光镜可以帮助减少眩光并增强阴影对比度,尤其是在户外拍摄时。
代码示例(使用自适应阈值化和霍夫线变换):
import cv2
import numpy as np
# ...(的 captureImage 函数)...
def processImage(im):
print('正在处理图像')
image = im
# 将图像转换为灰度
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 应用高斯模糊以减少噪声
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# 应用自适应阈值化
thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY_INV, 11, 2)
# 应用霍夫线变换来检测线
lines = cv2.HoughLinesP(thresh, 1, np.pi/180, threshold=50, minLineLength=50, maxLineGap=10)
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
length = sqrt((x2 - x1)**2 + (y2 - y1)**2)
print(f"顶部: ({x1}, {y1}), 底部: ({x2}, {y2}), 长度: {length}")
# 显示结果图像(可选)
cv2.imshow("Detected Line", image)
cv2.waitKey(0)
# ...(的代码的其余部分)...
请记住,没有一种万能的解决方案,适合情况的最佳方法取决于的特定设置和图像条件。尝试不同的技术和参数组合,以找到最适合的设置的方法。
标签:python,opencv,image-processing,computer-vision,coordinates From: 78605498