简体   繁体   English

如何使用 python 去除图像中图形周围的白色边框/边缘?

[英]How to remove the white border/edge around a figure in an image using python?

I want to remove the white border between the black mask and the body image我想删除黑色蒙版和身体图像之间的白色边框

Image input examples:图像输入示例:

在此处输入图像描述

Image output with thickness 1:图片 output 厚度为 1:

在此处输入图像描述

Image output with thickness 2:图片 output 厚度为 2:

在此处输入图像描述

I tried some games with Blur and thresholds that I found in here I also used this code to find and draw the contour我尝试了一些带有模糊和阈值的游戏,我在这里找到了我还使用此代码来查找和绘制轮廓

    thickness = 3
    image = cv2.imread('../finetune/22.png')
    blank_mask = np.zeros(image.shape, dtype=np.uint8)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    cnts = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]

    cv2.drawContours(image, cnts, -1, (255,0,0), thickness)
    cv2.imshow('image', image)
    cv2.imwrite('../finetune/22-'+str(thickness)+'r.png',image)
    cv2.waitKey()

However the contour I've found is the black mask edge and not the white line I played with the thickness and it works nice but on each image this contour is different, also the thickness is not equal throughout the figure然而,我发现的轮廓是黑色蒙版边缘,而不是我用厚度播放的白线,它工作得很好,但在每张图像上,这个轮廓都是不同的,而且整个图中的厚度也不相等

what is the best precise way to remove it?删除它的最佳精确方法是什么?

Here are two methods:这里有两种方法:

Method #1: cv2.erode()方法#1: cv2.erode()

You can use erosion is to erode away the boundaries of the white foreground object.您可以使用侵蚀来侵蚀掉白色前景 object 的边界。 Essentially the idea is to perform 2D convolution with a kernel.本质上,这个想法是使用 kernel 执行 2D 卷积。 A kernel can be created using cv2.getStructuingElement() where you can pass the shape and size of the desired kernel to create.可以使用cv2.getStructuingElement()创建 kernel,您可以在其中传递所需 kernel 的形状和大小来创建。 Typical kernels are cv2.MORPH_RECT , cv2.MORPH_ELLIPSE , or cv2.MORPH_CROSS .典型的内核是cv2.MORPH_RECTcv2.MORPH_ELLIPSEcv2.MORPH_CROSS The kernel slides through the image where a pixel is considered a 1 if all the pixels under the kernel is 1 otherwise it is eroded to 0 . kernel 滑过图像,如果 kernel 下的所有像素为1 1否则它被侵蚀为0 The net effect is that all pixels on the boundaries will be discarded depending on the shape and size of the kernel.最终效果是边界上的所有像素都将被丢弃,具体取决于 kernel 的形状和大小。 The thickness of the foreground decreases and is useful for removing small white noise or to detach objects.前景的厚度减小,可用于去除小的白噪声或分离对象。 You can adjust the strength of the erosion with the number of iterations to perform.您可以使用要执行的迭代次数来调整侵蚀的强度。

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
erode = cv2.erode(image, kernel, iterations=1)

Method #1: Opening with cv2.morphologyEx()方法 #1:使用cv2.morphologyEx()打开

The opposite to erosion is dilation which enhances the image.与腐蚀相反的是膨胀,它可以增强图像。 Typically, dialtion is performed after erosion to "normalize" the effect of the morphological operation.通常,在腐蚀之后执行拨号以“标准化”形态操作的效果。 OpenCV combines these steps into a single operation called morphological opening. OpenCV 将这些步骤组合成一个称为形态打开的单个操作。 Opening is just another name for erosion followed by dilation and will typically give you smoother results compared to only eroding.打开只是腐蚀后膨胀的另一个名称,与仅腐蚀相比,通常会给您更平滑的结果。

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
opening = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)

Result结果

在此处输入图像描述

You can experiment with the kernel shape and the number of iterations.您可以试验 kernel 形状和迭代次数。 To remove more noise, increase the kernel size and the number of iterations while to remove less, decrease the kernel size and the number of iterations.要去除更多噪声,请增加 kernel 大小和迭代次数,而要去除更少,请减小 kernel 大小和迭代次数。

import cv2

image = cv2.imread('1.png')
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
opening = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel, iterations=3)

cv2.imshow('opening', opening)
cv2.waitKey()

The answer below sent by nathancy show exactly the result I want to achieve but it does not helping me with my root problem下面由nathancy发送的答案准确地显示了我想要达到的结果,但它并没有帮助我解决我的根本问题

When I use drawContours I could draw the contours on my mask and improve it当我使用 drawContours 时,我可以在我的面具上绘制轮廓并改进它

So this is more information about my problem:所以这是关于我的问题的更多信息:

After I've got a mask using an image segmentation method I want to change the background (in the example I use black background) but I still have white contour between the new background and the figure使用图像分割方法获得蒙版后,我想更改背景(在示例中我使用黑色背景),但新背景和图形之间仍然有白色轮廓

Original image:原图:

https://drive.google.com/open?id=1P39VCEe2FTqkD6JbdM4ueMr_71C6nI42 https://drive.google.com/open?id=1P39VCEe2FTqkD6JbdM4ueMr_71C6nI42

Mask:面具:

https://drive.google.com/open?id=1LTHaclsDOxRJCI9t5bLg3PeanseRR9bc https://drive.google.com/open?id=1LTHaclsDOxRJCI9t5bLg3PeanseRR9bc

Output: Output:

https://drive.google.com/open?id=1-uQx77-fmMf_9qFSgNMBvo77Q6Ag8qEZ https://drive.google.com/open?id=1-uQx77-fmMf_9qFSgNMBvo77Q6Ag8qEZ

This is the code I use:这是我使用的代码:

    image = cv2.imread('../finetune/1.png')
    mask = cv2.imread('../finetune/1mask.png')

    output = np.zeros(image.shape, dtype=np.uint8)

    output[np.where(mask == 255)] = image[np.where(mask == 255)]

    cv2.imshow("output",output)
    cv2.imwrite('../finetune/1.output.png',output)

helping the answer above I can take the contour again and create new mask coordinately but I'm sure there is better elegant way to do so帮助上面的答案我可以再次获取轮廓并协调创建新的蒙版,但我确信有更好的优雅方式来做到这一点

to clarify, I want to improve the mask in order to prevent the white border when I put it on a new background澄清一下,我想改进蒙版以防止将其放在新背景上时出现白色边框

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

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