Python 图片中扭曲矩形的复原

日常生活中,手残党们经常会把一些照片拍歪,比如拍个证件、试卷、PPT什么的,

比如下面这本书的封面原本是个矩形,随手一拍就成了不规则四边形

想要把它变成规则的矩形,有什么办法呢?

在这里插入图片描述
你一定想到了 PS,因为网上很多教程就是这么教的

打开PS \Longrightarrow 滤镜 \Longrightarrow 镜头校正 \Longrightarrow 自定 \Longrightarrow 变换

可是这样手工的调整数值实在是费劲哟!!

在这里插入图片描述
下面我们来写个程序,自动将图片恢复到任意矩形!

程序实现

1. 打开图片并显示

import cv2 as cv
import numpy as np

path = './book.jpg'
src = cv.imread(path)

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)

h, w = get_window_size(src)

win_name = 'RecAdjust'
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()

2. 在图片中标记四个角点

在这里插入图片描述

src_copy = src.copy()

class Indexer:
    def __init__(self, bound=4):
        self.id = 0
        self.bound=bound
    
    def get_id(self):
        self.id = (self.id+1)%self.bound
        return (self.id-1)%self.bound+1

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)

points = []
indexer = Indexer()
win_name = 'RecAdjust'
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()
print(points)

3. 设定输出矩形大小

# W = int(input('输出图片宽度:'))
# H = int(input('输出图片高度:'))
W,H = 600, 800
target_points = [(0,0),(W,0),(W,H),(0,H)]

4. 求解透视变换矩阵

points, target_points = np.array(points, dtype=np.float32), np.array(target_points, dtype=np.float32)
M = cv.getPerspectiveTransform(points, target_points)
print('透视变换矩阵:',M)

5. 透视变换并保存图片

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()

output_file = 'result.jpg'
cv.imwrite(output_file, result)

结果如下
在这里插入图片描述
结果没有想象的完美,是因为书的封面已经不是一个平面了,书角翘起。。。

如果图片中的矩形在一个平面上的话,效果还是挺不错的!!

在这里插入图片描述

完整代码下载

可关注后免费下载喔:https://download.csdn.net/download/itnerd/12819535

猜你喜欢

转载自blog.csdn.net/itnerd/article/details/108429553