【问题标题】:Find dominant color on contour opencv在轮廓opencv上找到主色
【发布时间】:2018-10-17 08:47:14
【问题描述】:

我试图找到轮廓内的主色(黑色或白色)。 我正在使用 OpenCV 读取图像并在黑色图像上提取白色。这是我到目前为止得到的:

绿色轮廓是轮廓,蓝色线条是边界框。所以在这个例子中,我试图提取数字 87575220,但正如你所看到的,它还可以识别一些随机伪影,例如字母 G。我认为解决方案是找到轮廓内的主要颜色,该颜色应该是接近白色。不过我不知道该怎么做。

这是我目前拥有的代码:

import argparse
import cv2
import imutils
import numpy as np

parser = argparse.ArgumentParser()
parser.add_argument("--image", "-i", required=True, help="Image to detect blobs from")
args = vars(parser.parse_args())

image = cv2.imread(args["image"])
image = imutils.resize(image, width=1200)
grey = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
(minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(grey)
maxval_10 = maxVal * 0.5
ret, threshold = cv2.threshold(grey, maxval_10, 255, cv2.THRESH_BINARY)
canny = cv2.Canny(grey, 200, 250)
lines = cv2.HoughLines(canny, 1, np.pi / 180, 140)

print(maxVal)

theta_min = 60 * np.pi / 180.
theta_max = 120 * np.pi / 180.0
theta_avr = 0
theta_deg = 0
filteredLines = []
for rho, theta in lines[0]:
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a * rho
    y0 = b * rho
    x1 = int(x0 + 1000 * (-b))
    y1 = int(y0 + 1000 * (a))
    x2 = int(x0 - 1000 * (-b))
    y2 = int(y0 - 1000 * (a))

    cv2.line(image, (x1, y1), (x2, y2), (0, 0, 255), 2)

    if theta_min <= theta <= theta_max:
        filteredLines.append(theta)
        theta_avr += theta

if len(filteredLines) > 0:
    theta_avr /= len(filteredLines)
    theta_deg = (theta_avr / np.pi * 180) - 90
else:
    print("Failed to detect skew")

image = imutils.rotate(image, theta_deg)
canny = imutils.rotate(canny, theta_deg)

im2, contours, hierarchy = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# cv2.drawContours(image, contours, -1, (0, 255, 0), 1)
cv2.imshow('Contours', im2)

boundingBoxes = []
filteredContours = []

for cnt in contours:
    (x, y, w, h) = cv2.boundingRect(cnt)
    if (h > 20 and h < 90 and w > 5 and w < h):
        if cv2.contourArea(cnt, True) <= 0:
            boundingBoxes.append((x, y, w, h))
            filteredContours.append(cnt)

for x, y, w, h in boundingBoxes:
    cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2)

cv2.drawContours(image, filteredContours, -1, (0, 255, 0), 1)

cv2.imshow('Image', image)
cv2.imshow('Edges', canny)
cv2.imshow('Threshold', threshold)

cv2.waitKey(0)
cv2.destroyAllWindows()

这是原图:

【问题讨论】:

  • 能否也附上原图?

标签: python opencv


【解决方案1】:

在开始搜索数字之前,我会尝试获得投资回报率。您没有提供原始图像,因此此示例是使用您发布的图像(已绘制框和轮廓)制作的。不过,也应该与原版一起使用。步骤写在示例代码中。希望能帮助到你。干杯!

示例代码:

import cv2
import numpy as np

# Read the image and make a copy then create a blank mask
img = cv2.imread('dominant.jpg')
img2 = img.copy()
h,w = img.shape[:2]
mask = np.zeros((h,w), np.uint8)

# Transform to gray colorspace and perform histogram equalization
gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
equ = cv2.equalizeHist(gray)

# Transform all pixels above thershold to white
black = np.where(equ>10)
img2[black[0], black[1], :] = [255, 255, 255]

# Transform to gray colorspace and make a thershold then dilate the thershold
gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
kernel = np.ones((15,15),np.uint8)
dilation = cv2.dilate(thresh,kernel,iterations = 1)

# Search for contours and select the biggest one and draw it on mask
_, contours, hierarchy = cv2.findContours(dilation,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
cv2.drawContours(mask, [cnt], 0, 255, -1)

# Perform a bitwise operation
res = cv2.bitwise_and(img, img, mask=mask)

# Display the ROI
cv2.imshow('img', res)

结果:

【讨论】:

  • 我试过这样做,但它会在背景上选择一些东西。我想我可能只需要检查方形轮廓。
  • 它适用于这个图像。如果它在其他方面失败,您可以尝试将边界框的高度和宽度作为标准,而不是选择最大的轮廓。
  • 我裁剪了图像并将阈值 10 增加到 40,现在效果很好。谢谢!
  • 太棒了。很高兴您找到了解决方案。干杯!
【解决方案2】:

您可以从每个轮廓中创建一个蒙版:

mask = np.zeros(image.shape, dtype="uint8")
cv2.drawContours(mask, [cnt], -1, 255, -1)

然后计算掩码内所有像素的平均值:

mean = cv2.mean(image, mask=mask)

然后检查mean是否足够接近白色

【讨论】:

  • 它真的不起作用。它要么隐藏所有字符,要么显示大部分字符并仍然显示黑色文本。
  • 我认为您将不得不使用阈值...您能否也发布原始图像,以便我可以尝试?
  • 也不取平均值,而是使用 m33n 指出的直方图并检查轮廓主要是否包含黑色和白色像素可能会更好
【解决方案3】:

由于颜色空间属性,颜色和平均值不能很好地匹配。我会创建一个直方图并选择最常见的一个(也可以应用一些颜色下采样)

【讨论】:

    猜你喜欢
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 2011-11-27
    • 1970-01-01
    • 2012-01-16
    • 2020-06-08
    • 2012-11-06
    相关资源
    最近更新 更多