如何使用 OpenCV 检测图像中的波纹

Posted

技术标签:

【中文标题】如何使用 OpenCV 检测图像中的波纹【英文标题】:How to detect ripples in a image with OpenCV 【发布时间】:2019-05-03 18:07:52 【问题描述】:

所以我有一张沙丘的照片,目前看起来像这样。

我要做的是在 Python 中使用 opencv 识别图片中的涟漪。我只是在学习这个图书馆,所以我不知道图书馆里的所有怪癖。我做了一些研究,但找不到与这个类似的问题,这个特别困难,因为涟漪会产生阴影。我的预期结果应该与此相反,使所有的涟漪都比其他功能更突出。下面是一个男人的照片,他的头发是突出的特征。我想对下面沙丘中的涟漪做同样的事情。

以下代码是我下面的代码,这是我最终产品的输出,但仍需要一些工作。

 path = "C:/some path//to get//to my picture//Dune field_resize.jpg"


# image I'm using
img = cv2.imread ( path , cv2.IMREAD_GRAYSCALE )
kernel = np.ones ( (5 , 5) , np.uint8 )

# Canny edge detecting
edges = cv2.Canny ( img , 75 , 200 )
th , img = cv2.threshold ( img , 220 , 255 , cv2.THRESH_BINARY_INV );

# Copy the thresholded image.
img_floodfill = img.copy ()

# Mask used to flood filling.
# Notice the size needs to be 2 pixels than the image.
h , w = img.shape[:2]
mask = np.zeros ( (h + 2 , w + 2) , np.uint8 )

# Floodfill from point (0, 0)
cv2.floodFill ( img_floodfill , mask , (0 , 0) , 255 );

# Invert floodfilled image
img_floodfill_inv = cv2.bitwise_not ( img_floodfill )

# Combine the two images to get the foreground.
img_out = img | img_floodfill_inv

# Display images.
cv2.imwrite ( "Thresholded Image.png" , img )
cv2.imwrite ( "Floodfilled Image.png" , img_floodfill )
cv2.imwrite ( "Inverted Floodfilled Image.png" , img_floodfill_inv )
cv2.imwrite ( "Foreground.png" , img )
cv2.waitKey ( 0 )

cv2.imwrite ( "canny_edge.png" , edges )

img_erosion = cv2.erode ( img , kernel , iterations=1 )

cv2.waitKey ( 0 )
cv2.destroyAllWindows ()

【问题讨论】:

这是一个有趣的问题。但是,目前还不清楚预期的输出是什么。您能否编辑您的问题,提供有关您期望结果的更多详细信息? 刚刚添加了更多细节,希望它更有意义。 您似乎正在检测阴影。反转你的结果怎么样? 我同意,如果您可以发布一些内容(甚至是草图)来显示您想要的输出类型,那将会很有帮助。如果你不能,那么我建议查看 Haralick 纹理(还有其他纹理属性)。如果您对完全不同的方法持开放态度,那么您应该知道现在很多人都在用深度学习来解决这样的问题(例如,用于图像分割问题的 U-Net,看起来就像这样)。但这需要训练数据... 【参考方案1】:

这是一个使用一些过滤的简单方法

将图像转换为灰度 使用精明的边缘检测来寻找边缘 寻找轮廓 为每个轮廓找到其区域并使用最大阈值区域进行过滤

坎尼

检测到的涟漪

您可能需要调整cv2.Canny 或阈值区域参数。在 Canny 检测之后进行过滤的另一种可能方法是distinguish between straight and irregular lines。可能有更好的过滤方法,但这种简单的区域方法会产生大部分影响。

import cv2
import numpy as np

original_image = cv2.imread('1.jpg')
gray = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)

canny = cv2.Canny(gray, 50, 150)
cnts = cv2.findContours(canny.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

threshold_max_area = 165
for c in cnts:
    area = cv2.contourArea(c)
    if area < threshold_max_area:
        cv2.drawContours(original_image,[c], 0, (0,255,0), 1)

cv2.imshow('canny', canny)
cv2.imshow('found', original_image)

cv2.waitKey(0)
cv2.destroyAllWindows()

【讨论】:

以上是关于如何使用 OpenCV 检测图像中的波纹的主要内容,如果未能解决你的问题,请参考以下文章

如何使用opencv从图像中检测文本

教你如何使用 OpenCV检测图像中的轮廓

教你如何使用 OpenCV检测图像中的轮廓

如何使用 Java 改进 OpenCV 中的人脸检测

Python 如何使用 HoughLines 和 OpenCV 检测图像中的垂直线和水平线?

如何使用 OpenCV Python 检测颜色