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. 原图、目标图和变换图的对比。从文字内容可以看出第三张图是由第一张变换而来的。
    在这里插入图片描述
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PythonOpenCV实现直线检测,可以使用Hough变换来检测直线。Hough变换是一种常用的图像处理方法,可用于检测直线、圆等几何形状。 以下是一个简单的示例代码,使用Hough变换来检测直线并计算交点: ```python import cv2 import numpy as np # 读取图像 img = cv2.imread('test.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 边缘检测 edges = cv2.Canny(gray, 50, 150, apertureSize=3) # Hough变换检测直线 lines = cv2.HoughLines(edges, 1, np.pi/180, 200) # 计算交点 points = [] for i in range(len(lines)): for j in range(i+1, len(lines)): rho1, theta1 = lines[i][0] rho2, theta2 = lines[j][0] if abs(theta1 - theta2) < np.pi/4: continue a = np.array([[np.cos(theta1), np.sin(theta1)], [np.cos(theta2), np.sin(theta2)]]) b = np.array([rho1, rho2]) x0, y0 = np.linalg.solve(a, b) points.append((int(x0), int(y0))) # 绘制直线和交点 for line in lines: rho, theta = line[0] a = np.cos(theta) b = np.sin(theta) x0 = a*rho y0 = b*rho x1 = int(x0 + 1000*(-b)) y1 = int(y0 + 1000*(a)) x2 = int(x0 - 1000*(-b)) y2 = int(y0 - 1000*(a)) cv2.line(img, (x1,y1), (x2,y2), (0,0,255), 2) for point in points: cv2.circle(img, point, 5, (0,255,0), -1) # 显示图像 cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在代码中,首先读取图像并进行灰度转换和边缘检测。然后使用Hough变换检测直线,并计算交点。最后绘制直线和交点,并显示图像。 需要注意的是,在计算交点时,需要将两条直线的极坐标表示转换为直角坐标表示,并使用线性方程组求解。 希望这个例子能够帮助到你实现直线检测并计算交点。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值