Python图像处理学习笔记——基于单应性变换实现文档矫正功能(OpenCV)


一、 什么是单应性变换

考虑图 1 中所示的两个平面图像(书的顶部)。红点表示两个图像中的同一物理点。在计算机视觉术语中,我们称这些为相应的点。下图中以四种不同的颜色(红色、绿色、黄色和橙色)显示四个相应的点。 单应性变换将一个图像中的点映射到另一个图像中的相应点。

二、OpenCV中单应性变换的函数用法

# pts_src and pts_dst 分别为原图像和目标图像中对应像素点
# 组成的 numpy arrays,对应点的个数不少于4组
h, status = cv2.findHomography(srcPoints, dstPoints[, method[, ransacReprojThreshold[, mask[, maxIters[, confidence]]]]])

# 计算得到的h(homography)可用于仿射变换
# Size 为原图的大小
im_dst = cv2.warpPerspective(im_src, h, size)

三、基于OpenCV交互实现单应性变换

1. 导入库

import cv2
import numpy as np

2. 定义一个类实现鼠标点击获取像素坐标

class GetRoiMouse():

    def __init__(self, img):
        self.lsPointsChoose = []
        self.tpPointsChoose = []
        self.pointsCount = 0  # 顶点计数
        self.pointsMax = 4  # 最大顶点个数
        self.mouseWindowName = 'get four top'
        self.img = img  # 输入的图像

    def mouseclick(self):  # 显示一个窗口
        cv2.namedWindow(self.mouseWindowName)
        # opecv可以设置监听鼠标
        # setMouseCallback(windowName,onMouse())
        # 在onMouse中写点击鼠标时要进行的工作
        cv2.setMouseCallback(self.mouseWindowName, self.on_mouse)

        cv2.imshow(self.mouseWindowName, self.img)
        cv2.waitKey(0)
	# 检测当前点个数,满足要求时关闭图像显示窗口
    def checkPointsNum(self):
        if len(self.lsPointsChoose) == 4:
            print('I get 4 points!')
            cv2.destroyAllWindows()

    # OpenCV的鼠标响应函数,可以在内部定义鼠标的各种响应
    def on_mouse(self, event, x, y, flags, param):
        # 左键点击
        if event == cv2.EVENT_LBUTTONDOWN:
            print('left-mouse')
            self.pointsCount += 1
            print(self.pointsCount)
            point1 = (x, y)
            # 画出点击的位置
            img1 = self.img.copy()
            cv2.circle(img1, point1, 10, (0, 255, 0), 2)
            self.lsPointsChoose.append([x, y])
            self.tpPointsChoose.append((x, y))
            # 将鼠标选的点用直线连起来
            for i in range(len(self.tpPointsChoose) - 1):
                cv2.line(img1, self.tpPointsChoose[i], self.tpPointsChoose[i + 1], (0, 0, 255), 2)
            cv2.imshow(self.mouseWindowName, img1)
            self.checkPointsNum()

3. 实现方法

if __name__ == '__main__':
	# 读取原图像
    img_src = cv2.imread('img_src.jpg')
    # 调用上述类,获取原图像的像素点
    mouse1 = GetRoiMouse(img_src)
    mouse1.mouseclick()
    # 为方便下一步运算,需要将像素点的类型转换为浮点型数据
    pts_src = np.float32(mouse1.lsPointsChoose)
	
	# 读取目标图像
    img_dst = cv2.imread('img_dst.jpg')
    mouse2 = GetRoiMouse(img_dst)
    mouse2.mouseclick()
    # 获取对应点
    pts_dst = np.float32(mouse2.lsPointsChoose)
	# ----------------------------------------------------
	# 目标图像的尺寸
    dw, dh = img_dst.shape[1], img_dst.shape[0]
    # 通过findHomography计算变换矩阵h
    h, status = cv2.findHomography(pts_src, pts_dst, cv2.RANSAC, 5)
    # 将变换矩阵h带入仿射变换实现矫正
    img_out = cv2.warpPerspective(img_src, h, (dw, dh))
	# 展示结果 图像,拼接起来
    images = np.concatenate((img_src[0: dh, 0:dw, 0:3], img_dst, img_out), axis=1)
    # 窗口显示
    cv2.imshow('homography', images)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

4. 运行结果展示

使用手机拍摄了两张不同角度的kindle照片,文字内容不同可以区分两图像的本质区别。

  1. 首先, 选取原图中的需要矫正的区域的四个顶点
    在这里插入图片描述
  2. 按照相应的顺序,选取目标图像对应的四个顶点
    在这里插入图片描述
  3. 原图、目标图和变换图的对比。从文字内容可以看出第三张图是由第一张变换而来的。
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值