简体   繁体   English

OpenCV - 斑点/缺陷/异常检测

[英]OpenCV - Blob/ Defect/ Anomaly Detection

I'm doing an at-home project basically just for fun but I'm having more trouble than anticipated.我做一个家庭项目基本上只是为了好玩,但我遇到的麻烦比预期的要多。 I want to be able to find the pitch mark in this sample image.我希望能够在此示例图像中找到音高标记。 enter image description here在此处输入图像描述

I've followed some tutorials and things to load the image from a location and run simple blob detection on the image.我已经按照一些教程和事情从某个位置加载图像并在图像上运行简单的 blob 检测。 My code currently is as follows ->我的代码目前如下->

import cv2
import numpy as np

# Read in the image in grayscale
img = cv2.imread('/home/pi/Downloads/divot1.jpeg', cv2.IMREAD_GRAYSCALE)

params = cv2.SimpleBlobDetector_Params()
params.filterByArea = True
params.minArea = 50

# Determine which openCV version were using
if cv2.__version__.startswith('2.'):
    detector = cv2.SimpleBlobDetector(params)
else:
    detector = cv2.SimpleBlobDetector_create(params)

# Detect the blobs in the image
keypoints = detector.detect(img)
print(len(keypoints))

# Draw detected keypoints as red circles
imgKeyPoints = cv2.drawKeypoints(img, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)


# Display found keypoints
cv2.imshow("Keypoints", imgKeyPoints)
cv2.waitKey(0)

cv2.destroyAllWindows()

I understand that there are A LOT more image manipulation techniques when using openCV but I was hoping someone could point me in the right direction.我知道使用 openCV 时还有很多图像处理技术,但我希望有人能指出我正确的方向。 I've tried some things like various blur types to kind of get rid of some of the 'noise' of each single blade of grass.我尝试了一些方法,比如各种模糊类型,以消除每片草叶的一些“噪音”。 I also tried messing with a few parameters although I'm not sure the ones I was using were helping (min/maxAREA, color, convexity)我也尝试弄乱一些参数,尽管我不确定我使用的参数是否有帮助(最小/最大面积、颜色、凸度)

The end goal is to be able to find that dark brown abnormality in the image, and return the center "coordinate" of that shape.最终目标是能够找到图像中的深褐色异常,并返回该形状的中心“坐标”。

Sorry, I don't have time to implement it, but for this particular case, something like this should work:抱歉,我没有时间实现它,但是对于这种特殊情况,这样的事情应该可以工作:

  1. Google for "color picker" and find the correct HSV range of colors.谷歌“颜色选择器”并找到 colors 的正确 HSV 范围。 For this brown, it looks like you want a range of from about 20 degrees to about 40 degrees.对于这种棕色,看起来您想要大约 20 度到大约 40 度的范围。
  2. Convert your image to the HSV color space.将您的图像转换为 HSV 颜色空间。 hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
  3. Use cv2.inRange to create a mask of where the brown spots are.使用 cv2.inRange 创建棕色斑点所在位置的蒙版。 mask = cv2.inRange(hsv_img, (20,0,0), (40,255,255))掩码 = cv2.inRange(hsv_img, (20,0,0), (40,255,255))
  4. Convert your mask to a black and white image.将您的蒙版转换为黑白图像。 img2 = np.where(mask, np.uint8(255), np.uint8(0))
  5. Use cv2.findContours to find the brown spots.使用 cv2.findContours 找到褐色斑点。 contours,_ = cv2.findContours(img2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
  6. Get the largest spot.获得最大的位置。 brown_spot = sorted(contours, key=cv2.contourArea, reverse=True)[0]
  7. Draw the contour.画出轮廓。 cv2.drawContours(img, [brown_spot], -1, (255,0,0), 3)

There might be some things I missed or some mistakes with this, but I think you can play around with it and take it from here:)可能有一些我错过的东西或一些错误,但我认为你可以玩弄它并从这里拿走它:)

edit I overlooked the part where you also want the center coordinate.编辑我忽略了你也想要中心坐标的部分。 If you want the center of mass of the brown spot, get the average x coordinate of all of the x coordinates and the average y coordinate of all of the y coordinates.如果您想要棕色斑点的质心,请获取所有 x 坐标的平均 x 坐标和所有 y 坐标的平均 y 坐标。 That should be your center of mass coordinate.那应该是您的质心坐标。 If I remember correctly the contour has an extra dimension on it, which you may need to remove with np.squeeze.如果我没记错的话,轮廓上有一个额外的尺寸,您可能需要使用 np.squeeze 将其删除。 After doing that you can get the average of the y coordinates (the first column) with np.mean(brown_spot[:,0]) and the average of the x coordinates (the second column) with np.mean(brown_spot[:,1]).之后,您可以使用 np.mean(brown_spot[:,0]) 获得 y 坐标(第一列)的平均值,使用 np.mean(brown_spot[:, 1])。 cv2.findContours only finds perimeters and the spacing is not consistent, so your center of mass might be a little off. cv2.findContours 只查找周长并且间距不一致,因此您的质心可能有点偏离。 If you want a more accurate center of mass (or to also account for empty areas within the brown spot), you will have to use connectedComponents instead of findContours.如果你想要一个更准确的质心(或者还要考虑棕色点内的空白区域),你将不得不使用 connectedComponents 而不是 findContours。

Nobody mentioned blurring yet so I will.还没有人提到模糊,所以我会的。

The fine detail of the grass is equivalent to noise that will bother you in whatever you do with the picture as is.草的精细细节相当于噪音,无论您对图片做什么都会打扰您。 Blur it.模糊它。

Edit: since I was asked for some parameter-"less" approaches:编辑:因为我被要求提供一些参数 - “更少”的方法:

Saliency . 显着性

Or good old statistics.或者好的旧统计数据。

im = cv.imread("green-blurred.jpg")
yuv = cv.cvtColor(im, cv.COLOR_BGR2YCrCb) # or COLOR_BGR2YUV, should work equivalently here
#uv = yuv[:,:,(2,3)]
mean = np.mean(yuv, axis=(0,1))
std = np.std(yuv, axis=(0,1))
#mask = ((yuv - mean) / std >= 4.5).any(axis=2)
# EDIT: there needs to be an abs() on that difference, we want magnitudes, no signs
mask = (np.abs(yuv - mean) / std >= 4.5).any(axis=2)
mask_u8 = mask.astype(np.uint8) * 255
#grayscale = (np.abs(yuv - mean) / std / 5).max(axis=2)
cv.imshow("mask", mask_u8)
cv.waitKey(-1)

not a perfect approach but can probably be adjusted.不是一个完美的方法,但可能可以调整。

模糊

5 sigma 偏差作为灰度 YUV 任意通道的 4.5 sigma 偏差

Use whatever you like to localize the blob.使用任何你喜欢的东西来本地化 blob。 findContours would be an easy choice. findContours将是一个简单的选择。 Use cv::moments to get some statistics you can turn into a centroid (center of mass) for the blob.使用 cv::moments 获取一些统计信息,您可以将其转换为 blob 的质心(质心)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM