I am a beginner and I am trying to apply an outline to the white remote control on the left that shares the same color with the background. enter image description here

a = cv2.imread(file_name)
imgGray = cv2.cvtColor(a,cv2.COLOR_BGR2GRAY)

imgGray = cv2.GaussianBlur(imgGray,(11,11),20)

k5 = np.array([[-1,-1,-1],[-1,9,-1],[-1,-1,-1]])
imgGray = cv2.filter2D(imgGray,-1,k5)

cv2.namedWindow("Control")
cv2.createTrackbar("blocksize","Control",33,1000,f)
cv2.createTrackbar("c","Control",3,100,f)
while True:
    strel = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
    blocksize = cv2.getTrackbarPos("blocksize","Control")
    c = cv2.getTrackbarPos("c","Control")

    if blocksize%2==0:
        blocksize += 1
    thrash = cv2.adaptiveThreshold(imgGray,255,cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV,blockSize=blocksize,C=c)
    thrash1 = cv2.adaptiveThreshold(imgGray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,blockSize=blocksize,C=c)

    cv2.imshow("mean",thrash)
    cv2.imshow("gaussian",thrash1)
    #r,thrash = cv2.threshold(imgGray,150,255,cv2.THRESH_BINARY_INV)
    key = cv2.waitKey(1000)
    if key == 32 or iter == -1:
         break


edges = cv2.Canny(thrash,100,200)
cv2.imshow('sharpen',sharpen)
cv2.imshow('edges',edges)
cv2.imshow('grey ',imgGray)
cv2.imshow('thrash ',thrash)
cv2.waitKey(0)
circles = cv2.HoughCircles(imgGray,cv2.HOUGH_GRADIENT,1,60,param1=240,param2=50,minRadius=0,maxRadius=0)
contours,_ = cv2.findContours(thrash,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
putlabel(circles,a,contours)

这些都是我try 过的,我也try 过形态学操作,比如扩张、侵蚀、打开和关闭,但我仍然无法获得结果.

Below is my best result but the noise is too severe and the remote controller didn't get fully outlined. enter image description here

推荐答案

我想到了一种纯粹的图像处理方法.但结果并不像@Nathance所描述的那样准确

学说

太长,读不下go 了我使用的是Difference of Gaussians (DoG),这是一个两级边缘检测器.

  • 获取灰度图像.
  • 对其执行两种不同的模糊操作.
  • 减go 模糊的图像

模糊操作通常起到 suppress 高频的作用.通过减go 两种不同模糊操作的结果,我们得到一个带通滤波器.我想引用this blog中的一句话:"从另一个模糊图像中减go 一个模糊图像,可以保留介于两个模糊图像中保留的频率范围之间的空间信息."

我编写了一个简单的函数,返回两个模糊图像的差值:

def dog(img, k1, s1, k2, s2):
    b1 = cv2.GaussianBlur(img,(k1, k1), s1)
    b2 = cv2.GaussianBlur(img,(k2, k2), s2)
    return b1 - b2

方法

  • 获取灰度图像
  • 使用不同的内核大小和sigma值执行高斯模糊
  • 减go 模糊的图像
  • 应用大津阈值
  • 找到足够大面积的等高线
  • 根据轮廓的范围 Select 轮廓

Note:范围是一个轮廓的属性,它是contour area与其对应bounding rectangle area的比值.Taken from here

Code & Results

img = cv2.imread('path_to_image', cv2.IMREAD_UNCHANGED)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Function to perform Difference of Gaussians
def difference_of_Gaussians(img, k1, s1, k2, s2):
    b1 = cv2.GaussianBlur(img,(k1, k1), s1)
    b2 = cv2.GaussianBlur(img,(k2, k2), s2)
    return b1 - b2

DoG_img = difference_of_Gaussians(gray, 7, 7, 17, 13)

enter image description here

正如你所看到的,它起到了边缘检测器的作用.您可以改变内核大小(k1, k2)和sigma值(s1, s2)

# Applying Otsu Threshold and finding contours
th = cv2.threshold(DoG_img ,127,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
contours, hierarchy = cv2.findContours(th, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# Create copy of original image
img1 = img.copy()

# for each contour above certain area and extent, draw minimum bounding box  
for c in contours:
    area = cv2.contourArea(c)
    if area > 1500:
        x,y,w,h = cv2.boundingRect(c)
        extent = int(area)/w*h              
        if extent > 2000:
            rect = cv2.minAreaRect(c)
            box = cv2.boxPoints(rect)
            box = np.int0(box)
            cv2.drawContours(img1,[box],0,(0,255,0),4)

enter image description here

正如你所见,结果并不完美.在边缘检测过程中也会捕捉到物体的阴影(高斯差).您可以try 改变参数,以判断结果是否更好.

Python相关问答推荐

Twilio:CallInstance对象没有来自_的属性'

如何将带有逗号分隔的数字的字符串解析为int Array?

Python无法在已导入的目录中看到新模块

根据网格和相机参数渲染深度

使用scipy. optimate.least_squares()用可变数量的参数匹配两条曲线

在Pandas 日历中插入一行

使用mySQL的SQlalchemy过滤重叠时间段

时间序列分解

如何避免Chained when/then分配中的Mypy不兼容类型警告?

如何制作10,000年及以后的日期时间对象?

Python库:可选地支持numpy类型,而不依赖于numpy

C#使用程序从Python中执行Exec文件

如何在Python中找到线性依赖mod 2

提取相关行的最快方法—pandas

网格基于1.Y轴与2.x轴显示在matplotlib中

判断Python操作:如何从字面上得到所有decorator ?

根据Pandas中带条件的两个列的值创建新列

来自Airflow Connection的额外参数

Scipy差分进化:如何传递矩阵作为参数进行优化?

在round函数中使用列值