使用OpenCV对二维码进行畸变矫正的代码
本文介绍了使用OpenCV进行二维码畸变矫正的方法。通过检测二维码的四个角点,计算透视变换矩阵,并应用warpPerspective实现图像校正。核心步骤包括:使用QRCodeDetector检测二维码、order_points排序角点、getPerspectiveTransform计算变换矩阵。该方法能有效解决因拍摄角度或镜头畸变导致的二维码变形问题,提高识别率。文章还提供了完整的Python代
在现在这个互联网发展的时代二维码在生活中无处不在,手机扫码以成习以为常,但其中相机对二维码的识别却很复杂,本文主要介绍如何使用Opencv通过透视变换来实现二维码的畸变矫正也是其中的一部分。
以倾斜二维码为例这是原图片:

这是根据原二维码处理后的图片:

介绍及注意事项:
1.主要功能:
检测图像中的二维码
提取二维码的四个角点
计算透视变换矩阵
应用透视变换矫正畸变
保存和显示结果
2. 关键步骤:
使用`cv2.QRCodeDetector()`检测二维码
order_points()`函数确保四个角点按正确顺序排列
使用`cv2.getPerspectiveTransform()`计算变换矩阵
使用`cv2.warpPerspective()`应用变换
3. 使用方法:
替换`input_image`为你的畸变二维码图像路径
运行代码后,会显示原始图像(带二维码轮廓)和矫正后的图像
矫正后的图像会保存到`output_image`指定的路径
注意事项:
1. 确保安装了正确版本的OpenCV一般用pip:
pip install opencv-python opencv-contrib-python
2. 如果二维码检测失败,可以尝试:
调整图像对比度
确保二维码在图像中足够大且清晰
尝试不同的预处理方法(如阈值化)
3. 对于严重畸变的二维码,可能需要手动指定角点位置。
接下来进入主题:
1.载入opencv和库:
import cv2
import numpy as np
2.检测图像中的二维码并进行畸变矫正:
image_path: 输入图像路径
output_path: 矫正后图像保存路径(可选)
| 参数 | 类型 | 是否必需 | 说明 |
|---|---|---|---|
image_path |
string | 是 | 输入图像的路径(需畸变矫正的二维码图像) |
output_path |
string | 否 | 输出图像保存路径。若为 None,则函数可能直接返回矫正后的图像对象 |
核心目的:
用于 矫正含有二维码(QR Code)的图像畸变,提高二维码识别的准确率。主要解决因镜头畸变、拍摄角度倾斜或透视变形导致的二维码扭曲问题
技术实现:
畸变矫正:利用相机的内参矩阵(camera matrix)和畸变系数(distortion coefficients),通过 OpenCV 的 undistort() 或 remap() 函数消除径向/切向畸变。
透视校正:通过霍夫变换或特征点检测定位二维码边界,再使用透视变换(warpPerspective)将倾斜的二维码拉正。
def correct_qr_distortion(image_path, output_path=None):
(1)使用cv2.QRCodeDetector()检测二维码:
# 读取图像
image = cv2.imread(image_path)
if image is None:
raise ValueError("无法加载图像,请检查路径是否正确")
# 转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 初始化二维码检测器
qr_detector = cv2.QRCodeDetector()
# 检测二维码
retval, points, straight_qrcode = qr_detector.detectAndDecode(gray)
(2) order_points()函数确保四个角点按正确顺序排列:
if not retval:
print("未检测到二维码")
return None
# 将点转换为整数坐标
points = points.astype(int)
# 在原始图像上绘制二维码轮廓
cv2.polylines(image, [points], isClosed=True, color=(0, 255, 0), thickness=2)
(3)使用cv2.getPerspectiveTransform()计算变换矩阵:
# 获取二维码的四个角点
# 注意:points的顺序可能不一致,我们需要按左上、右上、右下、左下的顺序排列
rect = order_points(points.reshape(4, 2))
# 计算二维码的宽度和高度
(tl, tr, br, bl) = rect
# 计算新二维码的宽度
widthA = np.linalg.norm(br - bl)
widthB = np.linalg.norm(tr - tl)
maxWidth = max(int(widthA), int(widthB))
# 计算新二维码的高度
heightA = np.linalg.norm(tr - br)
heightB = np.linalg.norm(tl - bl)
maxHeight = max(int(heightA), int(heightB))
# 定义目标点
dst = np.array([
[0, 0],
[maxWidth - 1, 0],
[maxWidth - 1, maxHeight - 1],
[0, maxHeight - 1]], dtype="float32")
# 计算透视变换矩阵
M = cv2.getPerspectiveTransform(rect, dst)
(4) 使用`cv2.warpPerspective()`应用变换:
# 应用透视变换
warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
3.保存矩阵变换后的结果:
# 如果提供了输出路径,则保存结果
if output_path is not None:
cv2.imwrite(output_path, warped)
# 显示结果
cv2.imshow("Original with QR Code Outline", image)
cv2.imshow("Corrected QR Code", warped)
cv2.waitKey(0)
cv2.destroyAllWindows()
return warped
4. 把保存好的结果按四个点按左上、右上、右下、左下的顺序排列:
def order_points(pts):
"""
将四个点按左上、右上、右下、左下的顺序排列
参数:
pts: 包含四个点坐标的数组
返回:
排序后的点坐标
"""
# 初始化一个坐标数组,并将四个点相加求和
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
5 .替换和保存:
为了使用方便,这里可以替换使用图片将 input_image = "cs3.jpg" 替换为input_image =(你的图像路径)。
# 使用示例
if __name__ == "__main__":
input_image = "cs3.jpg" # 替换为你的图像路径
output_image = "corrected_qr_code.jpg" # 输出图像路径
corrected = correct_qr_distortion(input_image, output_image)
if corrected is not None:
print("二维码矫正完成并已保存!")
本文用的是vscode配置python开发环境编写opencv。利用cv2.QRCodeDetector()检测二维码,
order_points()函数确保四个角点按正确顺序排列,使用cv2.getPerspectiveTransform()计算变换矩阵,使用cv2.warpPerspective()应用变换,最后达到对二维码进行矫正的效果。
这是本文完整代码:
import cv2
import numpy as np
def correct_qr_distortion(image_path, output_path=None):
"""
检测图像中的二维码并进行畸变矫正
参数:
image_path: 输入图像路径
output_path: 矫正后图像保存路径(可选)
返回:
矫正后的图像
核心目的
用于 矫正含有二维码(QR Code)的图像畸变,提高二维码识别的准确率。主要解决因镜头畸变、拍摄角度倾斜或透视变形导致的二维码扭曲问题
技术实现
畸变矫正:利用相机的内参矩阵(camera matrix)和畸变系数(distortion coefficients),通过 OpenCV 的 undistort() 或 remap() 函数消除径向/切向畸变。
透视校正:通过霍夫变换或特征点检测定位二维码边界,再使用透视变换(warpPerspective)将倾斜的二维码拉正。
"""
# 读取图像
image = cv2.imread(image_path)
if image is None:
raise ValueError("无法加载图像,请检查路径是否正确")
# 转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 初始化二维码检测器
qr_detector = cv2.QRCodeDetector()
# 检测二维码
retval, points, straight_qrcode = qr_detector.detectAndDecode(gray)
if not retval:
print("未检测到二维码")
return None
# 将点转换为整数坐标
points = points.astype(int)
# 在原始图像上绘制二维码轮廓
cv2.polylines(image, [points], isClosed=True, color=(0, 255, 0), thickness=2)
# 获取二维码的四个角点
# 注意:points的顺序可能不一致,我们需要按左上、右上、右下、左下的顺序排列
rect = order_points(points.reshape(4, 2))
# 计算二维码的宽度和高度
(tl, tr, br, bl) = rect
# 计算新二维码的宽度
widthA = np.linalg.norm(br - bl)
widthB = np.linalg.norm(tr - tl)
maxWidth = max(int(widthA), int(widthB))
# 计算新二维码的高度
heightA = np.linalg.norm(tr - br)
heightB = np.linalg.norm(tl - bl)
maxHeight = max(int(heightA), int(heightB))
# 定义目标点
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))
# 如果提供了输出路径,则保存结果
if output_path is not None:
cv2.imwrite(output_path, warped)
# 显示结果
cv2.imshow("Original with QR Code Outline", image)
cv2.imshow("Corrected QR Code", warped)
cv2.waitKey(0)
cv2.destroyAllWindows()
return warped
def order_points(pts):
"""
将四个点按左上、右上、右下、左下的顺序排列
参数:
pts: 包含四个点坐标的数组
返回:
排序后的点坐标
"""
# 初始化一个坐标数组,并将四个点相加求和
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
# 使用示例
if __name__ == "__main__":
input_image = "cs3.jpg" # 替换为你的图像路径
output_image = "corrected_qr_code.jpg" # 输出图像路径
corrected = correct_qr_distortion(input_image, output_image)
if corrected is not None:
print("二维码矫正完成并已保存!")
谢谢观看!!
更多推荐



所有评论(0)