如何检测与背景融合的物体?

Syr*_*mid 3 python opencv image-processing computer-vision image-thresholding

我是初学者,我正在尝试将轮廓应用到左侧的白色遥控器上,该遥控器与背景颜色相同。 在此输入图像描述

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)
Run Code Online (Sandbox Code Playgroud)

这些是我尝试过的,我也尝试过形态学操作,如膨胀、腐蚀、开闭,但我仍然无法获得结果。

下面是我的最佳结果,但噪音太严重,而且遥控器的轮廓也没有完全清晰。 在此输入图像描述

nat*_*ncy 5

我认为简单的图像处理无法隔离与背景颜色相同的对象。因此我们必须转向深度/机器学习。这个想法是使用 U-2-Net 去除图像的背景,这将为我们提供前景中所有对象的掩模,然后使用白色的 HSV 颜色阈值来隔离对象。

这是通过 U-2-Net 运行去除背景后的结果蒙版

按位与隔离对象

现在我们可以使用传统的图像处理,因为我们可以区分前景和背景。接下来,我们使用较低/较高颜色范围的 HSV 颜色阈值来隔离白色,从而产生此蒙版。您可以使用HSV 颜色阈值脚本来确定下限/上限范围

现在,我们只需执行一些形态学操作即可清除任何噪声,找到轮廓,并按最大轮廓区域进行排序。假设最大的轮廓将是我们想要的对象。这是结果

代码

import cv2
import numpy as np

# Load image + mask, grayscale, Gaussian blur, Otsu's threshold
image = cv2.imread("1.jpg") # This is the original image
original = image.copy()
mask = cv2.imread("1.png") # This is the mask generated from U-2-Net
gray = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
bg_removed = cv2.bitwise_and(image, image, mask=thresh)

# HSV color thresholding
hsv = cv2.cvtColor(bg_removed, cv2.COLOR_BGR2HSV)
lower = np.array([0, 0, 0])
upper = np.array([179, 33, 255])
hsv_mask = cv2.inRange(hsv, lower, upper)
isolated = cv2.bitwise_and(bg_removed, bg_removed, mask=hsv_mask)
isolated = cv2.cvtColor(isolated, cv2.COLOR_BGR2GRAY)
isolated = cv2.threshold(isolated, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Morph operations to remove small artifacts and noise
open_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
opening = cv2.morphologyEx(isolated, cv2.MORPH_OPEN, open_kernel, iterations=1)
close_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, close_kernel, iterations=1)

# Find contours and sort by largest contour area
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
for c in cnts:
    cv2.drawContours(original, [c], -1, (36,255,12), 3)
    break

cv2.imshow("bg_removed", bg_removed)
cv2.imshow("hsv_mask", hsv_mask)
cv2.imshow('isolated', isolated)
cv2.imshow('original', original)
cv2.waitKey()
Run Code Online (Sandbox Code Playgroud)

如果有人有一种使用简单图像处理而不是深度/机器学习的方法,我很想知道如何!