百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

openCV进阶之二自动校准扫描图像生成鸟瞰图

toyiye 2024-06-21 11:55 7 浏览 0 评论

上一节介绍了如何openCV的透视转换方法的应用,并构建了一个基于给定四角点转换鸟瞰图的方法函数,这一节将继续这个运用,通过查找边缘的方法实现自动转换的功能。

实现步骤实际上很简单,只需要三步:

第一步:查找文档的边缘

第二步:通过边缘查找文档轮廓并找到四个角点的坐标

第三步:使用透视转换函数完成图像转换

下面的代码基于openCV/python的版本:openCV2.4/3+, python2.7/3+

上一章节我们完成了transform.py模块的构建,我们将在接下来的涉及图像四角点处理的问题中均会使用到。打开你的python编辑器,创建一个新的文档,并命名为scan.py。

# 导入必要的库
#导入上一节构建的模块和函数
from transform import four_point_transform
#记得安装scikit-image包,threshold-local函数帮助我们处理黑白图像
from skimage.filters import threshold_local 
import numpy as np
import argparse
import cv2
#imutils是一个很实用的图像处理库,比如resize/cropping/rotate等图像基本编辑
import imutils
 
# 构建解析器并解析参数
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True, help = "Path to the image to be scanned")
args = vars(ap.parse_args())

接下来就是第一步:边缘查找:

# 加载图像并计算新旧图像高度的比例,并拷贝一份,修改大小。
# 为了加快图像处理速度,同时使边缘检测步骤更加准确,
# 我们将扫描图像的高度调整为500像素。
# 我们还特别注意跟踪图像的原始高度与新高度的比值,
# 这将允许我们对原始图像而不是调整大小的图像执行扫描。
image = cv2.imread(args["image"])
ratio = image.shape[0] / 500.0
orig = image.copy()
image = imutils.resize(image, height = 500)
 
# 把图象转化为灰度, 并加模糊处理,然后查找边缘
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(gray, 75, 200)
 
# 显示原始图像和检测到的边缘图像
print("STEP 1: Edge Detection")
cv2.imshow("Image", image)
cv2.imshow("Edged", edged)
cv2.waitKey(0)
cv2.destroyAllWindows()

测试一下效果:

shell

python scan.py --image images/doc.jpg

图1:图像背景最后选择比较纯且和文档反差大的效果比较好

虽然背景有点不干净但是文档的边缘还是很明显的,接下来我们想办法查找文档的边缘并生成轮廓。

第二步:寻找轮廓:

事实上,在构建文档扫描器时,有一个非常重要的前提:扫描仪只是在一张纸上扫描。一张纸被假定为长方形,矩形有四条边。因此,我们可以创建一个简单的方法来帮助我们构建文档扫描器。我们假设图像中最大的轮廓恰好有四个点,这就是我们要扫描的那张纸。这也是一个相当安全的假设——当然,也可以人为的给定文档轮廓。

# 在边缘图像的基础上查找轮廓保留最大的一个,并在图像中标识出来
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:5]
 
# 循环处理
for c in cnts:
	# 大致轮廓
	peri = cv2.arcLength(c, True)
	approx = cv2.approxPolyDP(c, 0.02 * peri, True)
 
	# 如果查找的大致轮廓有四个角点,即假设为我们需要查找的
	if len(approx) == 4:
		screenCnt = approx
		break
 
# 显示文档的轮廓
print("STEP 2: Find contours of paper")
cv2.drawContours(image, [screenCnt], -1, (0, 255, 0), 2)
cv2.imshow("Outline", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行一下代码测试效果:shell中输入

python scan.py --image images/receipt.jpg

图2:按照图1的边缘查找不行,换这张背景比较单纯的图测试

正如您所看到的,我们已经成功地利用边缘检测图像找到了文档的轮廓(outline),我的收据周围的绿色矩形显示了轮廓(outline)。最后,让我们进入步骤3,这将是用到four_point_transform函数。

第三步:转换图像:构建移动文档扫描器的最后一步是取代表文档大纲的四个点,并应用透视图转换来获得自顶向下的图像“鸟瞰图”。

# 应用四点转换生成鸟瞰图
warped = four_point_transform(orig, screenCnt.reshape(4, 2) * ratio)
 
# 把变形的图像转化成灰度
warped = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)
T = threshold_local(warped, 11, offset = 10, method = "gaussian")
warped = (warped > T).astype("uint8") * 255
 
# 显示转换前后的图像
print("STEP 3: Apply perspective transform")
cv2.imshow("Original", imutils.resize(orig, height = 650))
cv2.imshow("Scanned", imutils.resize(warped, height = 650))
cv2.waitKey(0)

我们将把两个参数传递给four_point_transform:第一个参数是我们从磁盘加载的原始图像(不是调整大小的图像),第二个参数是表示文档的轮廓线,乘以调整大小的比例。

你可能会想,为什么要乘以调整后的比例? 我们乘以调整后的比例,因为我们进行了边缘检测,在调整后的高度=500像素的图像上发现了轮廓。但是,我们希望对原始图像进行扫描,而不是对调整大小的图像进行扫描,因此我们将轮廓点乘以调整大小的比例。

为了获得图像的黑白感觉,我们将扭曲后的图像转换为灰度图像,并应用自适应阈值。

好的,我们来运行一下效果:

shell

python scan.py --image images/receipt.jpg

图3:提取转换后的文档,看起来不错

好了,到目前为止,扫描图像到文档提取鸟瞰图的过程实现完成了。遗留问题:

实际上这个程序还有不少地方需要你的改进,比如要求转换的文档本身是规则的四边形,拍摄时尽量放在对比度明显的桌面背景,这样做的目的是为了避免边缘查找时出现多于四边的情况,多于四边的边缘后续轮廓查找会出现问题。也就是找不到合适的四边轮廓来匹配。

解决方案:可以采用人工标注四个角点的方式来提取轮廓更为可靠。因为在实际应用场景往往是不规则的文档。下一节我们来探讨这个方案实现过程。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码