这篇博客演示了如何使用4点OpenCV getPerspectiveTransform来构建一个文档扫描仪应用程序!
左图是原图,右图是应用透视变换得到的自顶向下的“鸟瞰图”
同样的“鸟瞰图”
橙色是最小外接矩形 boundingRect结果
绿色是面积最小外接矩形 minAreaRect的结果
红色是轮廓近似的结果
通过了findContours,轮廓检测来近似获取角点;
图中是矩形,因此用进来轮廓后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)