当前位置 博文首页 > Python图片处理之图片裁剪教程

    Python图片处理之图片裁剪教程

    作者:怪皮蛇皮怪 时间:2021-08-13 18:35

    目录
    • 一、操作流程
    • 二、代码分析
    • 三、懒人一键复制代码

    一、操作流程

    首先复制代码会吧?

    1.有张照片

    这是网上随便找的一张照片,自行保存测试

    在这里插入图片描述

    2.看看照片

    运行代码,其中show_img函数是展示照片

    3.选择角点

    按照左上,右上,右下,左下的顺序选择四个角点

    在这里插入图片描述

    如果担心自己选不好,可以直接去除我代码里的points的注释,那是我自己用的原版

    4.最终结果

    在这里插入图片描述

    二、代码分析

    import 没什么好说的

    #如果python没有安装cv2,那么就安装python-opencv就好
    import cv2 as cv
    import numpy as np

    获取图片的长宽

    #输入cv.imread后的图片,通过点击四个点选择要裁剪的部分
    def get_window_size(src, bound=600):
        h,w = src.shape[0], src.shape[1]
        if h > w:
            h, w = bound, int(w*bound/h)
        else:
            h, w = int(h*bound/w), bound
        return (h, w)
    
    

    通过鼠标获取图片的坐标点,顺序是左上,右上,右下,左下

    class Indexer:
        def __init__(self, bound=4):
            self.id = 0
            self.bound = bound
    
        def get_id(self):
            self.id = (self.id + 1)
            return (self.id)
    
    
    def on_EVENT_LBUTTONDOWN(event, x, y, flags, param):
        if event == cv.EVENT_LBUTTONDOWN:
            img = param['src']
            win_name = param['window']
            indexer = param['indexer']
            points = param['points']
    
            curr_id = indexer.get_id()
            points.append((x, y))
            print('第{}个顶点: ({},{})'.format(curr_id, x, y))
    
            cv.circle(img, (x, y), 10, (0, 0, 255), thickness=2)
            cv.putText(
                img,
                str(curr_id),  # 文字
                (x, y),  # 坐标
                cv.FONT_HERSHEY_PLAIN,
                5,  # 字号
                (0, 0, 255),  # 字体颜色
                thickness=2  # 粗细
            )
    
            cv.imshow(win_name, img)
    
    #输入cv.imread后的图片,通过点击四个点选择要裁剪的部分
    def get_points(src):
        points = []
        indexer = Indexer()
        h, w=get_window_size(src)
        win_name = 'get_points'
        cv.namedWindow(win_name, cv.WINDOW_NORMAL)
        cv.resizeWindow(win_name, width=w, height=h)
        cv.imshow(win_name, src)
        cv.setMouseCallback(win_name, on_EVENT_LBUTTONDOWN,
                            param={'src': src, 'window': win_name, 'indexer': indexer, 'points': points})
        cv.waitKey(0)
        cv.destroyAllWindows()
        if len(points)>4:
            return points[0:4]
        # print(points)
        # points=[(2, 14), (90, 50), (87, 194), (1, 204)]
        return points
    
    #输入cv.imread后的图片,展示图片长什么样
    def show_img(src):
        win_name = 'show_img'
        h, w=get_window_size(src)
        cv.namedWindow(win_name, cv.WINDOW_NORMAL)
        cv.resizeWindow(win_name, width=w, height=h)
        cv.imshow(win_name, src)
        cv.waitKey(0)
        cv.destroyAllWindows()
    

    将图片截取,并按照指定的长宽比恢复成矩形

    def photo_cut_restore(src,points,H,W):
    
        target_points = [(0, 0), (W, 0), (W, H), (0, H)]
        points, target_points = np.array(points, dtype=np.float32), np.array(target_points, dtype=np.float32)
        M = cv.getPerspectiveTransform(points, target_points)
        # print('透视变换矩阵:', M)
    
        result = cv.warpPerspective(src_copy, M, (0, 0))
        result = result[:H, :W]
        win_name = 'Result'
        cv.namedWindow(win_name, cv.WINDOW_NORMAL)
        cv.resizeWindow(win_name, width=W, height=H)
        cv.imshow(win_name,result)
        cv.waitKey(0)
        cv.destroyAllWindows()
        return  result
    

    主程序

    if __name__ == '__main__':
    
        path = './1.jpg'
        src = cv.imread(path)
        src_copy = src.copy()
    
         show_img(src)
    
    
        W = 20
        H = 20
        # points=[(112, 308), (175, 310), (176, 369), (113, 369)]
        
        points=get_points(src)
        n = 20
        W = int(W * n)
        H = int(H * n)
    
        result=photo_cut_restore(src_copy,points,H,W)
    
        output_file = 'result.jpg'
        cv.imwrite(output_file, result)
    

    三、懒人一键复制代码

    诶,气不气,好不容易一段段复制完,结果最后居然有一键复制的地方

    import cv2 as cv
    import numpy as np
    
    #输入cv.imread后的图片,通过点击四个点选择要裁剪的部分
    def get_window_size(src, bound=600):
        h,w = src.shape[0], src.shape[1]
        if h > w:
            h, w = bound, int(w*bound/h)
        else:
            h, w = int(h*bound/w), bound
        return (h, w)
    
    
    class Indexer:
        def __init__(self):
            self.id = 0
    
        def get_id(self):
            self.id = (self.id + 1)
            return (self.id)
    
    
    def on_EVENT_LBUTTONDOWN(event, x, y, flags, param):
        if event == cv.EVENT_LBUTTONDOWN:
            img = param['src']
            win_name = param['window']
            indexer = param['indexer']
            points = param['points']
    
            curr_id = indexer.get_id()
            points.append((x, y))
            print('第{}个顶点: ({},{})'.format(curr_id, x, y))
    
            cv.circle(img, (x, y), 10, (0, 0, 255), thickness=2)
            cv.putText(
                img,
                str(curr_id),  # 文字
                (x, y),  # 坐标
                cv.FONT_HERSHEY_PLAIN,
                5,  # 字号
                (0, 0, 255),  # 字体颜色
                thickness=2  # 粗细
            )
    
            cv.imshow(win_name, img)
    
    #输入cv.imread后的图片,通过点击四个点选择要裁剪的部分
    def get_points(src):
        points = []
        indexer = Indexer()
        h, w=get_window_size(src)
        win_name = 'get_points'
        cv.namedWindow(win_name, cv.WINDOW_NORMAL)
        cv.resizeWindow(win_name, width=w, height=h)
        cv.imshow(win_name, src)
        cv.setMouseCallback(win_name, on_EVENT_LBUTTONDOWN,
                            param={'src': src, 'window': win_name, 'indexer': indexer, 'points': points})
        cv.waitKey(0)
        cv.destroyAllWindows()
        if len(points)>4:
            return points[0:4]
        # print(points)
        # points=[(2, 14), (90, 50), (87, 194), (1, 204)]
        return points
    
    #输入cv.imread后的图片,展示图片长什么样
    def show_img(src):
        win_name = 'show_img'
        h, w=get_window_size(src)
        cv.namedWindow(win_name, cv.WINDOW_NORMAL)
        cv.resizeWindow(win_name, width=w, height=h)
        cv.imshow(win_name, src)
        cv.waitKey(0)
        cv.destroyAllWindows()
    
    def photo_cut_restore(src,points,H,W):
    
        target_points = [(0, 0), (W, 0), (W, H), (0, H)]
        points, target_points = np.array(points, dtype=np.float32), np.array(target_points, dtype=np.float32)
        M = cv.getPerspectiveTransform(points, target_points)
        # print('透视变换矩阵:', M)
    
        result = cv.warpPerspective(src_copy, M, (0, 0))
        result = result[:H, :W]
        win_name = 'Result'
        cv.namedWindow(win_name, cv.WINDOW_NORMAL)
        cv.resizeWindow(win_name, width=W, height=H)
        cv.imshow(win_name,result)
        cv.waitKey(0)
        cv.destroyAllWindows()
        return  result
    
    
    if __name__ == '__main__':
    
        path = './3.jpg'
        src = cv.imread(path)
        src_copy = src.copy()
    
        # show_img(src)
    
    
        W = 20
        H = 20
        # points=[(124, 182), (181, 177), (180, 243), (125, 266)]
        points=get_points(src)
        print(points)
        n = 20
        W = int(W * n)
        H = int(H * n)
    
        result=photo_cut_restore(src_copy,points,H,W)
    
        output_file = 'result.jpg'
        cv.imwrite(output_file, result)
    
    jsjbwy
    下一篇:没有了