How can I soften just the edges of this image

£可爱£侵袭症+ 提交于 2020-01-30 10:37:06

问题


I am using python and opencv to cut an image using a mask. The mask itself is quite jagged and so the resulting image becomes a bit jagged around the edges like below

Jagged image

Is there a way I can smooth out the edges so they look more like this without affecting the rest of the image?

Smoothed edge

Thanks SoS

** UPDATE **

Added the original jagged image without the annotation Original Jagged image


回答1:


Here is one way using OpenCV, Numpy and Skimage. I assume you actually have an image with a transparent background and not just checkerboard pattern.

Input:

import cv2
import numpy as np
import skimage.exposure


# load image with alpha channel
img = cv2.imread('lena_circle.png', cv2.IMREAD_UNCHANGED)

# extract only bgr channels
bgr = img[:, :, 0:3]

# extract alpha channel
a = img[:, :, 3]

# blur alpha channel
ab = cv2.GaussianBlur(a, (0,0), sigmaX=2, sigmaY=2, borderType = cv2.BORDER_DEFAULT)

# stretch so that 255 -> 255 and 127.5 -> 0
aa = skimage.exposure.rescale_intensity(ab, in_range=(127.5,255), out_range=(0,255))

# replace alpha channel in input with new alpha channel
out = img.copy()
out[:, :, 3] = aa

# save output
cv2.imwrite('lena_circle_antialias.png', out)

# Display various images to see the steps
# NOTE: In and Out show heavy aliasing. This seems to be an artifact of imshow(), which did not display transparency for me. However, the saved image looks fine

cv2.imshow('In',img)
cv2.imshow('BGR', bgr)
cv2.imshow('A', a)
cv2.imshow('AB', ab)
cv2.imshow('AA', aa)
cv2.imshow('Out', out)

cv2.waitKey(0)
cv2.destroyAllWindows()


I am by no means an expert with OpenCV. I looked at cv2.normalize(), but it did not look like I could provide my own sets of input and output values. So I also tried using the following adding the clipping to be sure there were no over-flows or under-flows:

aa = a*2.0 - 255.0
aa[aa<0] = 0
aa[aa>0] = 255


where I computed that from solving simultaneous equations such that in=255 becomes out=255 and in=127.5 becomes out=0 and doing a linear stretch between:

C = A*X+B
255 = A*255+B
0 = A*127.5+B
Thus A=2 and B=-127.5


But that does not work nearly as well as skimage rescale_intensity.




回答2:


These are some effects you can do with the PIL image library:

from PIL import Image, ImageFilter
im_1 = Image.open("/constr/pics1/russian_doll.png") 
im_2 = im_1.filter(ImageFilter.BLUR) 
im_3 = im_1.filter(ImageFilter.CONTOUR) 
im_4 = im_1.filter(ImageFilter.DETAIL) 
im_5 = im_1.filter(ImageFilter.EDGE_ENHANCE) 
im_6 = im_1.filter(ImageFilter.EDGE_ENHANCE_MORE) 
im_7 = im_1.filter(ImageFilter.EMBOSS) 
im_8 = im_1.filter(ImageFilter.FIND_EDGES) 
im_9 = im_1.filter(ImageFilter.SMOOTH) 
im_10 = im_1.filter(ImageFilter.SMOOTH_MORE) 
im_11 = im_1.filter(ImageFilter.SHARPEN)

# now save the images

im_2.save("/constr/picsx/russian_dol_BLUR.png") 
im_3.save("/constr/picsx/russian_doll_CONTOUR.png") 
im_4.save("/constr/picsx/russian_doll_DETAIL.png") 
im_5.save("/constr/picsx/russian_doll_EDGE_ENHANCE.png") 
im_6.save("/constr/picsx/russian_doll_EDGE_ENHANCE_MORE.png") 
im_7.save("/constr/picsx/russian_doll_EMBOSS.png") 
im_8.save("/constr/picsx/russian_doll_FIND_EDGES.png") 
im_9.save("/constr/picsx/russian_doll_SMOOTH.png") 
im_10.save("/constr/picsx/russian_doll_SMOOTH_MORE.png") 
im_11.save("/constr/picsx/russian_doll_SHARPEN.png")


来源:https://stackoverflow.com/questions/58097626/how-can-i-soften-just-the-edges-of-this-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!