文档扫描仪的构建——使用Python,OpenCV应用透视变换来获得图像的自顶向下的“鸟瞰图”

使用Python,OpenCV应用透视变换来获得图像的自顶向下的“鸟瞰图”

    • 1. 效果图
    • 2. 应用透视变换的步骤
    • 3. 优化:矩形角点的获取
    • 4. 源码
    • 参考

这篇博客演示了如何使用4点OpenCV getPerspectiveTransform来构建一个文档扫描仪应用程序!

1. 效果图

左图是原图,右图是应用透视变换得到的自顶向下的“鸟瞰图”

文档扫描仪的构建——使用Python,OpenCV应用透视变换来获得图像的自顶向下的“鸟瞰图”_第1张图片
同样的“鸟瞰图”
橙色是最小外接矩形 boundingRect结果
绿色是面积最小外接矩形 minAreaRect的结果
红色是轮廓近似的结果

文档扫描仪的构建——使用Python,OpenCV应用透视变换来获得图像的自顶向下的“鸟瞰图”_第2张图片

2. 应用透视变换的步骤

  1. 轮廓检测获取左图中矩形框的四个角点
  2. 对四个角点按(左上、右上、左下、右下进行排序)
  3. 确定新图像的宽度与高度;
  4. 获取转换矩阵;
  5. 应用透视变换获得“鸟瞰图”;

3. 优化:矩形角点的获取

通过了findContours,轮廓检测来近似获取角点;
图中是矩形,因此用进来轮廓后4个点来进行判断;其他的 如三角形、圆形、正方形、多边形等的检测可以参考我之前的博客;

4. 源码

# USAGE
#  python transform_example.py --image images/example_01.png --coords "[(73, 239), (356, 117), (475, 265), (187, 443)]"

# 导入必要的包
import argparse
import sys

import cv2
import imutils
import numpy as np
from imutils.perspective import four_point_transform

# 构建命令行参数及解析
# --image 原始图像路径
# 四点的坐标,ROI图像区域
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", default='images/example_01.png', help="path to the image file")
ap.add_argument("-c", "--coords", default='[(73, 239), (356, 117), (475, 265), (187, 443)]',
                help="comma seperated list of source points")
args = vars(ap.parse_args())

# 加载图像 并获取其坐标List
image = cv2.imread(args["image"])

pts = np.array(eval(args["coords"]), dtype="float32")
print(type(pts))
print(pts)


def getROI(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    edged = cv2.Canny(blurred, 75, 200)

    # 应用轮廓检测获取轮廓
    cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
                            cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    if cnts is not None:
        # 外接矩形
        (x, y, w, h) = cv2.boundingRect(cnts[0])
        peri = cv2.arcLength(cnts[0], True)
        approx = cv2.approxPolyDP(cnts[0], 0.04 * peri, True)
        cv2.rectangle(image, (x - 5, y - 5), (x + w, y + h), (0, 128, 255), 0)

        # 面积最小外接矩形
        box = cv2.minAreaRect(cnts[0])
        box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
        box = np.array(box, dtype="int")
        cv2.drawContours(image, [box], -1, (0, 255, 0), 2)

        # 展示输出图像
        # cv2.imshow("output", image)
        # cv2.waitKey(0)

        # 轮廓是由一系列顶点组成的;如果是三角形,将拥有3个向量. 如果是正方形/矩形则具有4个向量,如果是正方形,则宽高比在0.95~1.05之间
        if len(approx) == 4:
            print('rectangele')
            a = np.reshape(approx, (4, 2))
            for i in a:
                print(i)
                x = i[0]
                y = i[1]
                cv2.circle(image, (x, y), 8, (0, 0, 255), -1)
            return a
    return None


pts = getROI(image)
if pts is None:
    print("pts is None...")
    sys.exit()

print(pts)

# 应用点变换以获取鸟瞰视图
warped = four_point_transform(image, pts)

# 展示原始及变换后的图像
cv2.imshow("Original", image)
cv2.imshow("Warped", warped)
cv2.waitKey(0)

参考

  • https://www.pyimagesearch.com/2014/08/25/4-point-opencv-getperspective-transform-example/

你可能感兴趣的:(Python,OpenCV,Python,图像处理,opencv,计算机视觉,图像识别,鸟瞰图,轮廓检测)