0
点赞
收藏
分享

微信扫一扫

去除图片周围的像素填充

千白莫 2022-04-13 阅读 95

尝试写了一个去除图片周围像素填充的函数,大概测试了一下,功能没啥问题,可以去除四边任意的像素值的填充,当然会先检查一下的,对于上下或者左右的边框去除,有两种模式,一种是可以去除两边不同像素值的,一个是去除限定相同像素值的。

不过测试的图片是四周都是[15,15,15]的填充 

from PIL import Image, PngImagePlugin
import numpy as np

def crop_img_idex(mask, begin, stop, order = True):
    if order:
        sequen = 1
    else:
        sequen = -1
    id = 0  # 这里不先赋值 就会报错local variable 'id' referenced before assignment
    for id in range(begin, stop, sequen):
        if mask[id] > 0:
            break
    return id

def whether_to_rm(mask, bottom = False):
    to_rm = True

    if not bottom:
        if mask[1] > 0:
            to_rm = False
            print("无边框可以移除")
    elif bottom:
        if mask[-1] >0:
            to_rm =False
            print("无边框可以移除")
    return to_rm

def remove_one_edge(Img, imarray, top = True, bottom = False, left = False, right = False, diff = False):
    # top 0 h-1 bottom h-1 0 left 0 w-1
    w = Img.width  # 图片的宽
    h = Img.height  # 图片的高
    w_begin, h_begin, w_new, h_new = 0, 0, w, h

    if top or left:
        judge = imarray[0, 0]
    elif bottom == 1 or right:
        judge = imarray[h - 1, w - 1]

    mask = np.sum(imarray != judge, axis=-1) > 0


    if top or bottom:
        mask1 = np.sum(mask, axis=-1)
        if not whether_to_rm(mask1, bottom=bottom):
            return Img
        if top:
            h_begin = crop_img_idex(mask1, 0, h)
            h_begin = h_begin + 1
            print(f"将要剪裁上边界至像素{h_begin}")
        elif bottom:
            h_new = crop_img_idex(mask1, h-1, 0, order=False)
            h_new = h_new - 1
            print(f"将要剪裁下边界至像素{h_new}")
    if left or right:
        mask2 = np.sum(mask, axis=-2)
        if not whether_to_rm(mask2,bottom=right):
            return Img
        if left:
            w_begin = crop_img_idex(mask2, 0, w)
            w_begin = w_begin + 1
            print(f"将要剪裁左边界至像素{w_begin}")
        elif right:
            w_new = crop_img_idex(mask2, w-1, 0,order=False)
            w_new = w_new - 1
            print(f"将要剪裁右边界至像素{w_new}")
    Img = Img.crop((w_begin, h_begin, w_new, h_new))
    return Img

def rm_edges(Img,imarray,edge ):
    w = Img.width  # 图片的宽
    h = Img.height  # 图片的高
    w_begin, h_begin, w_new, h_new = 0, 0, w, h
    if edge.all == np.array([0,1,0,1]).all:
        judge = imarray[h - 1, w - 1]
    else:
        judge = imarray[0, 0]
    mask = np.sum(imarray != judge, axis=-1) > 0
    maskud = np.sum(mask, axis=-1)
    masklr = np.sum(mask, axis=-2)
    if edge[0]==1:
        h_begin = crop_img_idex(maskud, 0, h)
        h_begin = h_begin + 1
        print(f"将要剪裁上边界至像素{h_begin}")
    if edge[1]==1:
        h_new = crop_img_idex(maskud, h - 1, 0, order=False)
        h_new = h_new - 1
        print(f"将要剪裁下边界至像素{h_new}")
    if edge[2]==1:
        w_begin = crop_img_idex(masklr, 0, w)
        w_begin = w_begin + 1
        print(f"将要剪裁左边界至像素{w_begin}")
    if edge[3]==1:
        w_new = crop_img_idex(masklr, w - 1, 0, order=False)
        w_new = w_new - 1
        print(f"将要剪裁右边界至像素{w_new}")
    Img = Img.crop((w_begin, h_begin, w_new, h_new))
    return Img


def remove_edge(img, edge = None, style = "diff"):
    """
    img: 传入图片,格式为PIL格式,np格式,或者是路径
    edge: 为一个list[x,x,x,x] x为0或者1,如果为1则代表去除这条边的边框,顺序分别为上下左右,同时为1的两条边的边界可以是一样的也可以是不一样的,
    默认选项为diff
    style:["same", "diff"],same 表示去除的几个边的框框的像素值需要是一样的,diff表示只要框的一条边上像素值是一样的就可以去除
    当edge没传参的时候,默认按照上下左右顺序,尽可能去掉大宽度的边框
    """
    if type(img) == str:
        img = Image.open(img)
        imarray = np.array(img)
    elif type(img) is np.ndarray:
        imarray = img
        img = Image.fromarray(imarray)
    elif type(img) is PngImagePlugin.PngImageFile:
        imarray = np.array(img)
    else:
        print("对象既不是地址,也不是数组,PngImageFile")
        return 0
    #print(type(edge))
    if type(edge) == list:
        edge = np.array(edge)
    print(  (type(edge) is np.ndarray and (edge.ndim != 1 or edge.shape != (4,))) )
    if (type(edge) is None) and (type(edge) is not np.ndarray  or (type(edge) is np.ndarray and (edge.ndim != 1 or edge.shape != (4,)))):
        print("edge 传入参数错误!")
        return img

    if edge is not None and sum(edge) != sum(edge == 1):
        # 修正edge的数值
        for i in [0, 1, 2, 3]:
            if edge[i]<0:
                edge[i] = 0
            elif edge[i]>0:
                edge[i] = 1
    if edge is not None and sum(edge) == 0:
        print("无需修改")
        return img
    w = img.width  # 图片的宽
    h = img.height  # 图片的高

    if edge is not None and sum(edge) == 1:
        # 这个情况下 无论是diff还是same都是一样的
        img = remove_one_edge(img, imarray, edge[0]==1, edge[1]==1, edge[2]==1, edge[3]==1)
        print(1)
    elif edge is not None and sum(edge) == 2:
        edge1 = edge.reshape(2, 2)
        if np.sum((np.sum(edge1, axis=-1) == 2)):
            # 这里是对边 对边是区分diff和 same的
            print("这里是对边")
            if style == "diff":
                img = remove_one_edge(img, imarray, edge[0]==1, False, edge[2]==1, False)
                imarray = np.array(img)
                img = remove_one_edge(img, imarray, False, edge[1] == 1, False, edge[3] == 1)
            elif style == "same":
                img = rm_edges(img, imarray, edge)
        elif edge is not None and np.sum((np.sum(edge, axis=-1) == 2)):
            #这里是临边 临边其实不区分
            print("这里是临边")
            img = rm_edges(img, imarray, edge)
    elif edge is not None and sum(edge) >= 2:
        img = rm_edges(img, imarray, edge)
    elif edge == None:
        img = remove_one_edge(img, imarray, True, False, True, False)
        imarray = np.array(img)
        img = remove_one_edge(img, imarray, False, True, False, True)

    return img
path = "E:\\docu\\QQ\\file\\frame000.png"
img = Image.open(path)
#imarray = np.array(img)
# type(imarray)  imarray.shape imarray.ndim
img = remove_edge(img, [1,0,1,0])
print(img.width, img.height)
img.show()

 

举报

相关推荐

0 条评论