OpenCV删除背景 [英] OpenCV remove background
问题描述
我试图删除某些图像的背景,调整一些值,并使用诸如morphologyEx
之类的方法给我一个令人满意的结果,但仍然存在一些孔,在最后一种情况下,这些孔即使在迭代时也无法填充每个轮廓并使用-1
进行绘制.我可以看到阈值图像确实非常好,可以使线条整体成形,但是我不知道如何继续...
I am trying to remove the background of some images, tweaking some values and using some methods like morphologyEx
gives me an aceptable result but some holes still remaining, in this last case, the holes doesn't fill even iterating on every contour and drawing it with -1
. I can see that threshold image is really good, making the whole shape with lines, but I don't know how to continue...
更新 我已经更改了代码,以便获得更好的结果,但是仍然有一些漏洞...如果可以填补这些漏洞,该脚本将是完美的.
Update I've changed my code so I get better results but I'm still getting some holes... If I could fill theese holes, the script would be perfect.
def get_contrasted(image, type="dark", level=3):
maxIntensity = 255.0 # depends on dtype of image data
phi = 1
theta = 1
if type == "light":
newImage0 = (maxIntensity/phi)*(image/(maxIntensity/theta))**0.5
newImage0 = array(newImage0,dtype=uint8)
return newImage0
elif type == "dark":
newImage1 = (maxIntensity/phi)*(image/(maxIntensity/theta))**level
newImage1 = array(newImage1,dtype=uint8)
return newImage1
def sharp(image, level=3):
f = cv2.GaussianBlur(image, (level,level), level)
f = cv2.addWeighted(image, 1.5, f, -0.5, 0)
return f
original_image = imread('imagen.jpg')
# 1 Convert to gray & Normalize
gray_img = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
gray_img = sharp(get_contrasted(gray_img))
gray_img = normalize(gray_img, None, 0, 255, NORM_MINMAX, CV_8UC1)
imshow("Gray", gray_img)
# 2 Find Threshold
gray_blur = cv2.GaussianBlur(gray_img, (7, 7), 0)
adapt_thresh_im = cv2.adaptiveThreshold(gray_blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 1)
max_thresh, thresh_im = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
thresh = cv2.bitwise_or(adapt_thresh_im, thresh_im)
# 3 Dilate
gray = cv2.Canny(thresh, 88, 400, apertureSize=3)
gray = cv2.dilate(gray, None, iterations=8)
gray = cv2.erode(gray, None, iterations=8)
imshow("Trheshold", gray)
# 4 Flood
contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contour_info = []
for c in contours:
contour_info.append((
c,
cv2.isContourConvex(c),
cv2.contourArea(c),
))
contour_info = sorted(contour_info, key=lambda c: c[2], reverse=True)
max_contour = contour_info[0]
holes = np.zeros(gray_img.shape, np.uint8)
drawContours(holes, max_contour, 0, 255, -1)
imshow("Holes", holes)
mask = cv2.GaussianBlur(holes, (15, 15), 0)
mask = np.dstack([mask] * 3) # Create 3-channel alpha mask
mask = mask.astype('float32') / 255.0 # Use float matrices,
img = original_image.astype('float32') / 255.0 # for easy blending
masked = (mask * img) + ((1 - mask) * (0,0,1)) # Blend
masked = (masked * 255).astype('uint8')
imshow("Maked", masked)
waitKey()
0原始
推荐答案
使用大小增加的核迭代地对孔图像进行形态学封闭.但是,在执行此操作之前,我建议您调整孔图像的大小(使用最近邻插值法),这样就不必使用巨大的内核.在以下代码(C ++)中,我将孔图像的大小调整为其原始尺寸的25%.
Iteratively perform a morphological closing of your holes image using a kernel of increasing size. But, before doing this I suggest you resize the holes image (using nearest-neighbor interpolation) so you don't have to use huge kernels. In the following code (C++), I resized the holes image to 25% of its original dimensions.
要减少对边界的影响,请在应用迭代结束之前使用 copyMakeBorder 添加恒定的零边界.当我们在这里使用15次迭代时,使图像周围的边界大于15.
To reduce the effects on borders add a constant border of zeros using copyMakeBorder before you apply the iterative closing. As we are using 15 iterations here, make the border around the image larger than 15.
步骤是
- 调整孔图像的大小
- 添加零边框
- 使用大小逐渐增加的内核迭代关闭图像
- 删除边框
- 现在我们有一个小口罩.将此蒙版调整为原始图像大小
代码使用C ++.我对python不太熟悉.
The code is in C++. I'm not very familiar with python.
// read the image and the holes
Mat im = imread("koAl2.jpg");
Mat holes = imread("GuICX.jpg", 0);
// resize
Mat small, bordered;
resize(holes, small, Size(), .25, .25);
// add a zero border
int b = 20;
copyMakeBorder(small, bordered, b, b, b, b, BORDER_CONSTANT, Scalar(0));
// close
for (int i = 1; i < 15; i++)
{
Mat kernel = getStructuringElement(MORPH_ELLIPSE, cv::Size(2*i+1, 2*i+1));
morphologyEx(bordered, bordered, MORPH_CLOSE, kernel, Point(-1, -1), 1);
}
// remove border
Mat mask = bordered(Rect(b, b, small.cols, small.rows));
// resize the mask
Mat largeMask;
resize(mask, largeMask, Size(im.cols, im.rows));
// the foreground
Mat fg;
im.copyTo(fg, largeMask);
除了将底部的背景区域作为前景之外,输出(不是原始比例)看起来不错.
The output (not to original scale) looks fine except that it takes the background region at the bottom as foreground.
这篇关于OpenCV删除背景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!