python png 边缘_Python图像处理-如何删除某些轮廓并将值与周围像素混合?

I'm doing a project with depth image. But I have problems with noise and failed pixel reading with my depth camera. There are some spots and contours (especially edges) that have zero value. How to just ignore this zero value and blend it with surrounding values?

I have tried dilation and erosion (morph image processing), but I still can't get the right combination. It indeed removed some of the noise, but I just need to get rid of zeros at all points

Image Example:

The zero value is the darkest blue (I'm using colormap)

To illustrate what I want to do, please refer to this poor paint drawing:

I want to get rid the black spot (for example black value is 0 or certain value), and blend it with its surround.

Yes, I'm able to localized the spot using np.where or the similar function, but I have no idea how to blend it. Maybe a filter to be applied? I need to do this in a stream, so I need a fairly fast process, maybe 10-20 fps will do. Thank you in advance!

Update :

Is there a way other than inpaint? I've looked for various inpaints, but I don't need as sophisticated as impainting. I just need to blend it with simple line, curve, or shape and 1D. I think inpaint is an overkill. Besides, I need them to be fast enough to be used for video stream 10-20 fps, or even better.

解决方案

Here is one way to do that in Python/OpenCV.

Use median filtering to fill the holes.

Read the input

Convert to gray

Threshold to make a mask (spots are black)

Invert the mask (spots are white)

Find the largest spot contour perimeter from the inverted mask and use half of that value as a median filter size

Apply median filtering to the image

Apply the mask to the input

Apply the inverse mask to the median filtered image

Add the two together to form the result

Save the results

Input:

import cv2

import numpy as np

import math

# read image

img = cv2.imread('spots.png')

# convert to gray

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold

mask = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)[1]

# erode mask to make black regions slightly larger

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))

mask = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel)

# make mask 3 channel

mask = cv2.merge([mask,mask,mask])

# invert mask

mask_inv = 255 - mask

# get area of largest contour

contours = cv2.findContours(mask_inv[:,:,0], cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

contours = contours[0] if len(contours) == 2 else contours[1]

perimeter_max = 0

for c in contours:

perimeter = cv2.arcLength(c, True)

if perimeter > perimeter_max:

perimeter_max = perimeter

# approx radius from largest area

radius = int(perimeter_max/2) + 1

if radius % 2 == 0:

radius = radius + 1

print(radius)

# median filter input image

median = cv2.medianBlur(img, radius)

# apply mask to image

img_masked = cv2.bitwise_and(img, mask)

# apply inverse mask to median

median_masked = cv2.bitwise_and(median, mask_inv)

# add together

result = cv2.add(img_masked,median_masked)

# save results

cv2.imwrite('spots_mask.png', mask)

cv2.imwrite('spots_mask_inv.png', mask_inv)

cv2.imwrite('spots_median.png', median)

cv2.imwrite('spots_masked.png', img_masked)

cv2.imwrite('spots_median_masked.png', median_masked)

cv2.imwrite('spots_removed.png', result)

cv2.imshow('mask', mask)

cv2.imshow('mask_inv', mask_inv )

cv2.imshow('median', median)

cv2.imshow('img_masked', img_masked)

cv2.imshow('median_masked', median_masked)

cv2.imshow('result', result)

cv2.waitKey(0)

cv2.destroyAllWindows()

Threshold image as mask:

Inverted mask:

Median filtered image:

Masked image:

Masked median filtered image:

Result:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值