使用Canny edge创建一个掩码 - 更新

时间:2017-09-04 19:19:01

标签: python opencv image-processing

我想用提供的图像中的白菜找到。我已经有一个使用颜色阈值处理的前一个问题的实现,但是它需要我手动输入HSV或RGB值,我需要一种自适应的控制方式,并考虑使用canny edge来查找边缘然后创建一个掩码。

下面是color thesholding的实现,它是canny的理想输出。

Sample image

Masked

Using find contours

# Import the necessary packages
import numpy as np
import argparse
import cv2
import glob

def auto_canny(image, sigma=0.33):
    # compute the median of the single channel pixel intensities
    v = np.median(image)

    # apply automatic Canny edge detection using the computed median
    lower = int(max(0, (1.0 - sigma) * v))
    upper = int(min(255, (1.0 + sigma) * v))
    edged = cv2.Canny(image, lower, upper)

    # return the edged image
    return edged

# Construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True,
    help = "Path to the image")
args = vars(ap.parse_args())
image = cv2.imread(args["image"])
cv2.imshow("Image", image)


gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (3, 3), 0)

auto = auto_canny(blurred)

cv2.imshow("Image", auto)
cv2.imwrite("newimage1.jpg", auto)



(_, cnts, _) = cv2.findContours(auto.copy(), cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)

if len(cnts) > 0:
    # sort the contours and find the largest one -- we
    # will assume this contour correspondes to the area
    # of my phone
    cnt = sorted(cnts, key = cv2.contourArea, reverse = True)[0]
    cv2.drawContours(image, [cnt], -1, (0, 255, 0), 2)


cv2.imshow("Tracking", image)
cv2.imwrite("newimage2.jpg", image)
cv2.waitKey(0)

cv2.waitKey(0)

结果:

Canny Output Outcome

我的思维过程是使用canny来找到边缘然后使用findcontours来获得最大轮廓并创建一个应该是卷心菜的面具。但是,这似乎不起作用,因为canny输出的结果有很多边缘。

我认为在应用canny边缘检测之前我应该​​做一些预处理,但我不太清楚应用什么技术来预处理。

编辑:

阅读一些建议并尝试了那些我知道如何做的建议,首先我将其转换为HSV并将图像拆分为相应的H,s和v。实施2种方法,结果如下,任何建议如何提高?

# Import the necessary packages
import numpy as np
import argparse
import cv2
import glob

def auto_canny(image, sigma=0.33):
    # compute the median of the single channel pixel intensities
    v = np.median(image)

    # apply automatic Canny edge detection using the computed median
    lower = int(max(0, (1.0 - sigma) * v))
    upper = int(min(255, (1.0 + sigma) * v))
    edged = cv2.Canny(image, lower, upper)

    # return the edged image
    return edged

# Construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True,
    help = "Path to the image")
args = vars(ap.parse_args())
image = cv2.imread(args["image"])
cv2.imshow("Image", image)
newImage = image.copy()

hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
blurred = cv2.GaussianBlur(hsv, (3, 3), 0)

#cv2.imshow("HSV image", blurred)

#now to seperate and only extract hue image
h,s,v = cv2.split(blurred)

cv2.imshow("H", h)
#cv2.imshow("S", s)
#cv2.imshow("V", v)

thresh = cv2.adaptiveThreshold(h, 255,
    cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 11, 4)
cv2.imshow("adaptive1", thresh)
cv2.imwrite("adaptive1.jpg", thresh)

(_, cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)

auto = auto_canny(h)
cv2.imshow("canny", auto)
cv2.imwrite("canny1.jpg", auto)


(_, cnts2, _) = cv2.findContours(auto.copy(), cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)

if len(cnts) > 0:
    # sort the contours and find the largest one -- we
    # will assume this contour correspondes to the area
    # of my phone
    cnt = sorted(cnts, key = cv2.contourArea, reverse = True)[0]
    cv2.drawContours(image, [cnt], -1, (0, 255, 0), 2)

cv2.imshow("adaptive2", image)
cv2.imwrite("adaptive2.jpg", image)

if len(cnts2) > 0:
    # sort the contours and find the largest one -- we
    # will assume this contour correspondes to the area
    # of my phone
    cnt = sorted(cnts2, key = cv2.contourArea, reverse = True)[0]
    cv2.drawContours(newImage, [cnt], -1, (0, 255, 0), 2)

cv2.imshow("canny2", newImage)
cv2.imwrite("canny2.jpg", newImage)

cv2.waitKey(0)

自适应:

adaptive

contour

的Canny:

canny

contour

2 个答案:

答案 0 :(得分:3)

您还可以在色彩空间中设置图像的三维直方图,如果您知道目标是场景中的主要对象,则可以在主要颜色空间(聚类)周围设置边界,然后使用该直方图。分段。这很可能是我想要的。

答案 1 :(得分:2)

不要转换为灰度,转换为某些HSV colorspace并尝试将绿色对象分割出来。

使用adaptiveThreshold而非canny,它可以很好地在本地找到最佳边缘水平