如何使用OpenCV检测图像中的涟漪

3
所以我有一张沙丘的图片,看起来像是这样的。enter image description here 我的目标是使用Python中的opencv识别图片中的波纹。我正在学习这个库,因此我不知道库内所有的细节。我做了一些研究,但没有找到类似于这种问题的解决方案,这个问题特别困难,因为波纹会产生阴影。我预期的结果应该是相反的,使所有的波纹比其他特征更加突出。下面是一个男人头发突出的图片,我想用同样的方法处理下面沙丘中的波纹。

image here 以下是我现在已有的代码及其最终产品的输出,但仍需要进行一些改进。

 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 ()

enter image here


这是一个有趣的问题。然而,预期输出并不是非常清晰。您能否编辑您的问题,提供更多关于您期望的结果的细节? - Paul92
刚刚添加了一些更详细的内容,希望现在能更加明白。 - Alex
你似乎正在检测阴影。那么反转一下你的结果呢? - Paul92
我同意,如果您能发布一些东西,即使是草图,展示您想要的输出类型,那将会很有帮助。如果您无法这样做,那么我建议您查看Haralick纹理(还有其他纹理属性)。如果您愿意采用完全不同的方法,那么您应该知道,现在有很多人正在使用深度学习攻击此类问题(例如,针对图像分割问题的U-Net,这似乎是一个好选择)。但是这需要训练数据... - Matt Hall
1个回答

3

这里有一个简单的方法,使用一些过滤器

  • 将图像转换为灰度
  • 使用Canny边缘检测来查找边缘
  • 查找轮廓
  • 对于每个轮廓,找到其面积并使用最大阈值面积进行过滤

Canny

enter image description here

检测到的波纹

enter image description here

您可能需要调整cv2.Canny或阈值面积参数。在Canny检测后进行过滤的另一个可能的方法是区分直线和不规则线条。可能有更好的过滤方法,但这种简单的面积方法可以获得大部分波纹。

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()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接