前言
随着科技的飞速发展,二维码作为一种信息载体,已经广泛应用于我们的日常生活中。无论是支付、身份验证还是信息传播,二维码都发挥着不可替代的作用。然而,在实际应用中,我们常常会遇到一个问题:由于拍摄角度、设备性能等因素的影响,导致二维码出现倾斜,从而影响识别效率。为此,本文将为大家介绍一种基于透射变换的二维码倾斜校正方法,帮助大家解决这一难题。
一、实现方法
首先,通过对图像进行二值化操作,获取二值化背景,之后进行形态学变换处理二维码区域。接下来,借助轮廓分析方法,通过凸包逼近多边形以及四边形近似获取的四个角点。最后,依据这四个角点的位置,我们应用透视变换技术对二维码进行了矫正,以确保其准确性和可读性。
二、实现代码
import cv2
import numpy as np
def sort_vertices_clockwise(vertices):
"""将四边形的四个顶点按照顺时针排序"""
# 找到y坐标最小的点(即最低点),如果有多个最低点,则选择x坐标最小的点
lowest_idx = np.argmin(vertices[:, 1])
lowest_point = vertices[lowest_idx]
# 将最低点移动到数组的起始位置
vertices = np.roll(vertices, -lowest_idx, axis=0)
# 计算其他三个点相对于最低点的极角
other_points = vertices[1:]
ref_point = vertices[0]
angles = np.arctan2(other_points[:, 1] - ref_point[1], other_points[:, 0] - ref_point[0])
# 根据极角对顶点进行排序
sorted_indices = np.argsort(angles)
sorted_vertices = np.vstack((ref_point, other_points[sorted_indices]))
return sorted_vertices
# 图片路径
path = r"F:\cv_traditional\1725413298229.png"
# 读取图片,转换为灰度图
img = cv2.imread(path, 0)
print(img.shape)
# 二值化处理,设置阈值50,将图片转换为二值图像
ret, thd = cv2.threshold(img, 50, 255, cv2.THRESH_BINARY_INV)
# 定义结构元素,用于形态学操作
kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 21))
# 对二值图像进行闭运算,填充轮廓内的孔洞
close = cv2.morphologyEx(thd, cv2.MORPH_CLOSE, kernel1)
# 查找轮廓
contours, _ = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 找到面积最大的轮廓
max_contour = max(contours, key=cv2.contourArea)
# 计算最大轮廓的凸包
hull = cv2.convexHull(max_contour)
# 计算凸包的周长,并设置逼近多边形的精度
epsilon = 0.02 * cv2.arcLength(hull, True)
# 使用approxPolyDP函数逼近多边形
approx = cv2.approxPolyDP(hull, epsilon, True)
# 将轮廓点转换为1维数组
vertices_1d = np.array([np.squeeze(point) for point in approx])
# 打印顺时针排序后的顶点
print(sort_vertices_clockwise(vertices_1d))
# 绘制最大轮廓
cv2.drawContours(img, [approx], -1, (0, 255, 0), 3)
# 获取图像的宽度和高度
h, w = img.shape
# 定义变换后的目标点坐标
dst_point1 = [0, 0]
dst_point2 = [w, 0]
dst_point3 = [w, h]
dst_point4 = [0, h]
# 将排序后的顶点转换为浮点数
ori = np.float32(sort_vertices_clockwise(vertices_1d))
# 定义目标坐标点
dst = np.float32([dst_point1, dst_point2, dst_point3, dst_point4])
# 计算透射变换矩阵
M = cv2.getPerspectiveTransform(ori, dst)
# 应用透射变换
transformed_image = cv2.warpPerspective(img, M, (700, 700))
# 显示原始图像和变换后的图像
cv2.imshow("原始图像", img)
cv2.imshow("变换后的图像", transformed_image)
# 等待按键后关闭窗口
cv2.waitKey(0)
三,效果
倾斜图片:
校正后图片: