简体   繁体   English

使用Canny Edge创建遮罩-已更新

[英]Using Canny edge to create a mask - updated

I would like to use find the cabbage in the image provided. 我想使用提供的图像中找到白菜。 I already have an implementation with a previous question using colour thresholding, however it required me to manually enter HSV or RGB values, i require an adaptive way of thesholding and thought of using canny edge to find edges and then create a mask. 我已经有了一个使用颜色阈值的上一个问题的实现,但是它需要我手动输入HSV或RGB值,我需要一种自适应的保持方式,并考虑使用Canny边缘查找边缘然后创建蒙版。

Below is the implentation from colour thesholding which is the desired output from canny. 以下是色彩保持的效果,这是canny的理想输出。

样本图片

蒙面

使用寻找轮廓

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

Results: 结果:

坎尼输出 结果

My thought process is to use canny to find edges and then use findcontours to get the biggest contour and create a mask which should be the cabbage. 我的思维过程是使用canny查找边缘,然后使用findcontours获得最大轮廓,并创建一个应该是白菜的蒙版。 However, this does not seem to be working as the result from canny output has a lot of edges. 但是,这似乎不起作用,因为精明输出的结果有很多优势。

I think i should do some pre processing before applying the canny edge detection but i'm not too sure what what techniques to apply for pre processing. 我认为我应该在应用Canny边缘检测之前进行一些预处理,但是我不太确定要应用哪些技术进行预处理。

EDIT: 编辑:

Read through the few suggestions and tried out those that i have an idea of how to do, first i converted it to HSV and split the image into respective H, s and v. Implemented 2 methods with the results below, any suggestions on how to improve? 通读一些建议,并尝试一些我有想法的建议,首先将其转换为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: 适应性:

自适应

轮廓

Canny: 精明:

谨慎的

轮廓

You could also set up a 3d histogram of your image in color space and if you know that your target is the primary object in the scene, you can algorythmically set up bounds around the primary color space (clustering) and then use that to segment. 您还可以在色彩空间中设置图像的3d直方图,如果您知道目标是场景中的主要对象,则可以在算法上围绕主要色彩空间设置边界(聚类),然后使用该边界进行分割。 That is likely what I would go for. 那可能就是我想要的。

Don't convert to grayscale, convert to some HSV colorspace and try and segment out the green objects. 不要转换为灰度,不要转换为某些HSV色彩空间,并尝试分割出绿色对象。

Use adaptiveThreshold rather than canny, it does a good job of finding the best edge level locally 使用adaptiveThreshold而不是canny,可以很好地在本地找到最佳边缘级别

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

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