在选择图像轮廓时如何避免对图像(条形图)进行分组?

时间:2019-05-27 14:31:49

标签: python opencv computer-vision cv2

我正在从图表图像中提取单个条形的长度。在大多数情况下,它都可以正常工作,但在某些情况下,轮廓将2条形为1,这对我的原因不利。我尝试了canny,dilate,腐蚀和配色方案的不同组合。它仅稍微改善了结果。如何避免分组?这是完整的代码和一张图片。您也可以使用此图像运行以查看问题。 enter image description here

from scipy.spatial import distance as dist
from imutils import perspective
from imutils import contours
import numpy as np
import argparse
import imutils
import cv2

def midpoint(ptA, ptB):
    return ((ptA[0] + ptB[0]) * 0.5, (ptA[1] + ptB[1]) * 0.5)

image = cv2.imread("somefile.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (7, 7), 0)

#edged=cv2.Laplacian(gray, cv2.CV_8U, gray, ksize=7)

edged = cv2.Canny(gray, 30, 50)
cv2.imwrite("test00.png", edged)
edged = cv2.dilate(edged, None, iterations=1)
cv2.imwrite("test01.png", edged)
edged = cv2.erode(edged, None, iterations=1)
cv2.imwrite("test02.png", edged)

cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)


pixelsPerMetric = 100

for c in cnts:
    orig = image.copy()
    box = cv2.minAreaRect(c)
    box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
    box = np.array(box, dtype="int")
    print(box)

    box = perspective.order_points(box)
    cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2)

    for (x, y) in box:
        cv2.circle(orig, (int(x), int(y)), 5, (0, 0, 255), -1)

    (tl, tr, br, bl) = box
    (tltrX, tltrY) = midpoint(tl, tr)
    (blbrX, blbrY) = midpoint(bl, br)

    (tlblX, tlblY) = midpoint(tl, bl)
    (trbrX, trbrY) = midpoint(tr, br)

    cv2.circle(orig, (int(tltrX), int(tltrY)), 5, (255, 0, 0), -1)
    cv2.circle(orig, (int(blbrX), int(blbrY)), 5, (255, 0, 0), -1)
    cv2.circle(orig, (int(tlblX), int(tlblY)), 5, (255, 0, 0), -1)
    cv2.circle(orig, (int(trbrX), int(trbrY)), 5, (255, 0, 0), -1)

    cv2.line(orig, (int(tltrX), int(tltrY)), (int(blbrX), int(blbrY)),
             (255, 0, 255), 2)
    cv2.line(orig, (int(tlblX), int(tlblY)), (int(trbrX), int(trbrY)),
             (255, 0, 255), 2)

    dA = dist.euclidean((tltrX, tltrY), (blbrX, blbrY))
    dB = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))


    dimA = dA / pixelsPerMetric
    dimB = dB / pixelsPerMetric

    cv2.putText(orig, "{:.1f}in".format(dimA),
                (int(tltrX - 15), int(tltrY - 10)), cv2.FONT_HERSHEY_SIMPLEX,
                0.65, (255, 255, 255), 2)
    cv2.putText(orig, "{:.1f}in".format(dimB),
                (int(trbrX + 10), int(trbrY)), cv2.FONT_HERSHEY_SIMPLEX,
                0.65, (255, 255, 255), 2)

    cv2.imshow("Image", orig)
    cv2.waitKey(0)

enter image description here

1 个答案:

答案 0 :(得分:1)

该图像易于分割。条形的颜色恰好是RGB=(245,222,179)。您可以使用OpenCV的函数inRange查找这种颜色的像素。在此功能中,我们需要按BGR顺序指定颜色,因为这是OpenCV默认情况下读取图像的方式。在这种情况下,如果图像使用JPEG压缩(这是有损的,因此会稍微改变像素值),我会选择一个较大的范围:

image = cv2.imread("somefile.png")
mask = cv2.inRange(image, (177, 220, 243), (181, 224, 247))

此图像mask现在具有完全分开的条形:

bars