【python实现图像矫正 全能扫描王!】

全能扫描王app里面有一个对图像进行矫正的功能,实际上是通过四点法的仿射变换来进行操作的。选取文档的四个角点,然后计算仿射变换矩阵来对图像进行矫正。下面通过一段python程序来进行简单实现,功能为:通过顺时针点击文档的左上,右上,右下,左下四个角点来对其进行图像矫正。代码如下:

# coding=utf-8
# 导入相应的python包
import numpy as np
import cv2

def order_points(pts):
    # 参考ref[1]
    # 初始化坐标点
    rect = np.zeros((4, 2), dtype = "float32")

    # 获取左上角和右下角坐标点
    s = pts.sum(axis = 1)
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]

    # 分别计算左上角和右下角的离散差值
    diff = np.diff(pts, axis = 1)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]

    return rect

def four_point_transform(image, pts):
    #参考ref[1]
    # 获取坐标点,并将它们分离开来
    rect = order_points(pts)
    (tl, tr, br, bl) = rect

    # 计算新图片的宽度值,选取水平差值的最大值
    widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
    maxWidth = max(int(widthA), int(widthB))

    # 计算新图片的高度值,选取垂直差值的最大值
    heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    maxHeight = max(int(heightA), int(heightB))

    # 构建新图片的4个坐标点
    dst = np.array([
        [0, 0],
        [maxWidth - 1, 0],
        [maxWidth - 1, maxHeight - 1],
        [0, maxHeight - 1]], dtype = "float32")

    # 获取仿射变换矩阵并应用它
    M = cv2.getPerspectiveTransform(rect, dst)
    # 进行仿射变换
    warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))

    # 返回变换后的结果
    return warped

def on_mouse(event, x, y, flags, param):
    global timg, points
    img2 = timg.copy()
    point0 = (0, 0)
    if event == cv2.EVENT_LBUTTONDOWN:         #左键点击
        point1 = (x,y)
        points.append([x,y])
        print(x,y)
        cv2.circle(img2, point1, 4, (0,255,0), 4)
        cv2.imshow('origin', img2)
    return point0

if __name__ == '__main__':
    global points, timg 
    xscale, yscale = 0.5, 0.5  # 通过放大图像来使得点击位置更加精确
    points = []
    oimg = cv2.imread('test.png')
    oshape = oimg.shape
    timg = cv2.resize(oimg, (int(oshape[1]/xscale), int(oshape[0]/yscale))) # 放大图像
    print(timg.shape)
    cv2.imshow('origin', timg)
    cv2.setMouseCallback('origin', on_mouse)
    cv2.waitKey(0)   # 点完4个角点之后随便按一个键盘按键结束操作
    cv2.destroyAllWindows()
    points = np.array(points, dtype=np.float32)
    points[:,0] *= oshape[1] / int(oshape[1]/xscale)  # 还原像素位置的大小
    points[:,1] *= oshape[0] / int(oshape[0]/yscale)
    warped = four_point_transform(oimg, points)
    # cv2.imwrite('warped.png', warped ) # 保存图像
    cv2.imshow('origin', warped)
    cv2.waitKey(0) 
    cv2.destroyAllWindows()

实验效果如下:

原始图片:                  

点击四个角点:

随便按一个键盘按键结束操作,随后显示矫正后的图像:

Done!

 

Reference:

[1]. https://blog.csdn.net/wzz18191171661/article/details/99174861

                                                                                                #一天天的不务正业

 

  • 8
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,我可以回答您的问题。图像矫正是一种重要的图像处理技术,它可以将图像旋转、平移、缩放等操作,使其更加清晰、易于分析和处理。下面是利用 OpenCV 和 Python 快速实现图像矫正的步骤: 1. 导入必要的库 ``` import cv2 import numpy as np ``` 2. 读取图像并转换为灰度图像 ``` img = cv2.imread('your_image_path.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ``` 3. 检测图像中的边缘 ``` edges = cv2.Canny(gray, 50, 150, apertureSize=3) ``` 4. 检测图像中的直线 ``` lines = cv2.HoughLines(edges, 1, np.pi/180, 200) ``` 5. 对检测到的直线进行排序,以便找到最长的两条直线 ``` lines = sorted(lines, key=lambda x: x[0][0], reverse=False) line1 = lines[0] line2 = lines[-1] ``` 6. 计算直线的交点,以确定旋转角度 ``` rho1, theta1 = line1[0] rho2, theta2 = line2[0] a = np.cos(theta1) b = np.sin(theta1) x0 = a * rho1 y0 = b * rho1 c = np.cos(theta2) d = np.sin(theta2) x1 = c * rho2 y1 = d * rho2 intersection = np.linalg.solve([[a, b], [c, d]], [x0, y1]) angle = np.arctan2(y1 - intersection[1], x1 - intersection[0]) angle = angle * 180 / np.pi ``` 7. 旋转图像并进行矫正 ``` (h, w) = img.shape[:2] center = (w // 2, h // 2) M = cv2.getRotationMatrix2D(center, angle, 1.0) rotated = cv2.warpAffine(img, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE) ``` 这样就可以快速实现图像矫正了。希望我的回答能够帮到您!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值