How can I soften just the edges of this image

后端 未结 2 2019
陌清茗
陌清茗 2021-01-27 19:46

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

Ja

相关标签:
2条回答
  • 2021-01-27 20:10

    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")
    
    0 讨论(0)
  • 2021-01-27 20:16

    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.

    0 讨论(0)
提交回复
热议问题