002.01 图片去外框处理范例

主题: 002.01 图片去外框处理范例

建檔日期: 2019/08/26
更新日期: None
语言: Python 3.7.4, PIL Pillow 6.1.0., tkinter 8.6
系统: Win10 Ver. 10.0.17763 繁体中文版(TW)

002.01 图片去外框处理范例

程序库的熟练还是要多写程序, 才会了解一些相的使用细节, 下面是有关图片去外框的处理, 内容不想作的太复杂, 所以有些地方, 并没有列入考虑.

说明:

1. 去外框的方式是在图片上, 以鼠标左键点击要去掉的部份的一个点, 寻找附近在颜色误差范围内的点, 都改为白色, 可以重复点击处理, 只能回到上一个图片.

2. 图文件的文件名在程序中, 没作档案选择的功能, 也没加入存盘的功能

3. 图文件尺寸太大可能在显示会超出屏幕, 不在考虑中.

4. 因为使用递回呼叫, 图片太大或太复杂可能会超出递回呼叫次数的要求, 仅设为2000次, 有必要可以再加大到数万次.

5. 因为图片中的边缘是以误差值来界定, 所以简单的图片可以设大的误差值, 一次作到要求, 对于复杂的图片, 只能一点一点来作.

結果

1. 简单的图(颜色简单, 本体与外围颜色差距大, 通常一次点选就能完成)

002.01 图片去外框处理
002.01 图片去外框处理

2. 复杂的图(指的是本体的颜色色与外围的颜色过于接近, 而且有太多不同的颜色成份, 需经过多次的点选处理)

002.01 图片去外框处理

程序

from tkinter import *
from PIL import Image, ImageTk

class display():
    # Canvas的图片显示
    def __init__(self, widget, imageObj):
        self.center = (int(imageObj.width/2), int(imageObj.height/2))
        self.photo = ImageTk.PhotoImage(image=imageObj)
        self.image = widget.create_image(self.center, image=self.photo)

def check(x0, y0):
    # 确认图点颜色是不要转换成白点
    r, g, b = im.getpixel((x0,y0))
    checked[x0][y0] = True
    if limit[0][0] <= r <= limit[0][1]:
        if limit[1][0] <= g <= limit[1][1]:
            if limit[2][0] <= b <= limit[2][1]:
                return True
    return False

def check_point(x0, y0, new_points):
    # 检查图点要不要处理
    # 超出图面, 已在要处理清单中, 颜色不对, 或已处理的点, 不处理
    if 0<=x0<im.width and 0<=y0<im.height:
        if (x0, y0) not in new_points:
            if not checked[x0][y0]:
                if check(x0,y0):
                    new_points.append((x0, y0))

def fill(points):
    # 处理清单中的点, 还有上下左右四点是否加清单中待处理
    global checked, count
    count += 1
    print('Recursion count :', count)

    if points==[]:
        return

    new_points = []
    for point in points:
        x = point[0]
        y = point[1]
        checked[x][y] = True

        if check(x, y):
            im_new.putpixel((x,y), (255,255,255))
            check_point(x-1, y, new_points)
            check_point(x+1, y, new_points)
            check_point(x, y-1, new_points)
            check_point(x, y+1, new_points)

    # 待处理清单, 递回再处理
    points = new_points[:]
    fill(points)

def process(event):
    global old_x, old_y, click_again, limit, trigger, points, im_new, checked, image01, im_old, im, error, count

    # 处理中, 不再处理新事件
    if not trigger:
        return
    trigger = False

    # 超出图片范围, 改为在图片范围
    if event.x >= im.width:
        x = im.width - 1
    else:
        x = event.x
    if event.y >= im.height:
        y = im.height - 1
    else:
        y = event.y

    # 取得图点颜色, 并设定误差范围
    r, g, b = im.getpixel((event.x, event.y))
    limit = [(r-error, r+error), (g-error, g+error), (b-10, b+error)]

    # 设定起点为鼠标左键点选位置
    points = [(event.x, event.y)]

    # 所有的点都未处理
    checked = [[False for i in range(im_new.height)] for j in range(im_new.width)]

    # 递回次数计算初值
    count = 0

    # 处理图片, 并显示
    fill(points)
    image01 = display(can01, im_new)

    # 只保留前一张原图
    im_old = im.copy()
    im = im_new.copy()

    # 可再接受新的点选事件
    trigger = True

def change_error():
    # 输入误差值事件
    global error
    error = int(input('give the error value'))

def undo():
    # Undo 回前一张图片, 只能Undo一次
    global im_new, im_old, image01, can01
    im_new = im_old.copy()
    image01 = display(can01, im_new)

trigger = True
error = 30  # 误差初值
font = 'times 20 bold'
filename = '5.jpg' # 图片文件名

im = Image.open(filename)

root = Tk() # 两个Canvas显示原图及新图+两个Button功能为设误差值及Undo

can00 = Canvas(root, bg='green', width=im.width, height=im.height)
can01 = Canvas(root, bg='green', width=im.width, height=im.height)
but10 = Button(root, bg='green', text = 'Set error value', font=font, fg='white', command=change_error)
but11 = Button(root, bg='green', text = 'Undo just one time', font=font, fg='white', command=undo)

can00.grid(row=0, column=0)
can01.grid(row=0, column=1)
but10.grid(row=1, column=0)
but11.grid(row=1, column=1)

# 两个画布都可以接受点选
can00.bind('<Button-1>', process)
can01.bind('<Button-1>', process)

im_old = im.copy()
im_new = im.copy()
image00 = display(can00, im)

# 递回最大次数
sys.setrecursionlimit(2000)

root.mainloop()

Jason Yang

讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!