脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Python - Python图片处理之图片裁剪教程

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

2021-11-15 10:35怪皮蛇皮怪 Python

这篇博文的目的是从图片中提取一定的矩形区域作为新的图片 简单来说:我的全家福丢了,所以我想从以前的房间照片里,提取出其中的全家福并重新打印一张(忽视画质问题)现在我就是这么个目的,需要的朋友可以参考下

一、操作流程

首先复制代码会吧?

1.有张照片

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

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

2.看看照片

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

3.选择角点

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

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

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

4.最终结果

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

二、代码分析

import 没什么好说的

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

获取图片的长宽

?
1
2
3
4
5
6
7
8
#输入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)

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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()

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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

主程序

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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)

三、懒人一键复制代码

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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)

到此这篇关于python图片处理之图片裁剪教程的文章就介绍到这了,更多相关python图片裁剪内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_43958086/article/details/117250288

延伸 · 阅读

精彩推荐