【图像处理】基于图像处理的纸张检测和提取

背景

  • 给导师看了下自己的毕设系统,建议是可以添加一些互动性。可以在纸张检测上弄一下,也就是拍一张带有纸张的图像,然后提取出纸张边缘并提取出来。
  • 提取出纸张有很多种方法,以前做车牌识别系统的时候,利用图像处理的方法定位出车牌的位置,用的是轮廓提取的方法, 首先找蓝色的区域(所以只能支持蓝色车牌),然后找到矩形轮廓区域,车牌矩形满足一定的宽高比例,然后就可以找到车牌了。然而纸张并不像车牌那样规规矩矩,有时候纸张会出现形变等情况,而且纸张内部如果写有字,可能也会影响纸张的提取,颜色提取就更不用说了,字迹和光照也会影响的。如何进行纸张检测和提取是一个有意思的研究。

方法

似乎有很多方法可以提取纸张,比如直线检测,找到直线相交的四个点,也可以基于边缘检测和轮廓法,也可以利用深度学习方案,例如HED网络、RCF网络等,本毕设的背景较为简单,因此采用图像处理方法进行检测。然而,图像处理说简单其实似乎也不简单。这里我使用轮廓提取的方法来提取。

步骤:

(准备:白色A4纸张,背景桌面尽量纯色,然后再弄几张有代表性的复杂背景桌面,opencv,python)

  • 缩放,统一尺寸
    由于是手机拍摄的,大部分是百万像素以上,4000x3000的像素,缩放到1000x750,方便处理,然后copy一张灰度的图像做主要处理图像。
  • 滤波处理
    中值滤波,核大小为3x3,手机拍出来一般没啥噪声点,稍微简单处理下就就行了,或者不加。另外要说明的是,如果图像拍出来是模糊的,再滤波一下,会检测不到边缘的。
  • 二值化
    用大津阈值分割法,自适应进行二值化。白色纸张
  • 边缘检测
    有很多很多种边缘检测方法,最好用Canny,而且一般都用Canny法。边缘提取效果非常好。
  • 提取轮廓
    轮廓的提取,opencv有findContours()函数,直接调用就行了,返回的contours对象,包含有n个带有m个点的数据,这m个点围起来就是一个轮廓,一共有n组。
  • 筛选轮廓1
    第一次筛选,使用的方法很粗暴简单,提取的轮廓必须要大于100000,也就是说,750x1000=750000,要轮廓面积大于整个图像的1/7.5的,其它的直接pass掉,纸张肯定在图像里面,并且涵盖大部分区域
  • 筛选轮廓2
    第二次筛选,要做一些处理,首先是提取凸包,得到凸包的角点,然后对这个凸包n边形进行拟合,拟合的结果,肯定是一个多边形,然后判断这个多边形是否为4边形就ok了。
  • 仿射变换,提取
    在上一步中,会直接得到4个点,将这四个点进行排序,然后进行放射变换,就可以提取需要的结果了。

结果

不足之处,仍然有一些提取错误的,这些错误的图像,包含了纸张,但是也含有其它的部分,这是在提取轮廓这个步骤中失误的,因此在提取轮廓中,如何进行进一步筛选则是未来的一个问题,不过对于个人的毕设,利用上述步骤已经完全足够,因为背景并不复杂,结果如下:
下面全是图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
提取纸张边框,可以通过以下步骤实现: 1. 图像预处理:使用图像处理库(例如OpenCV)对原始图像进行灰度化、二值化、降噪等处理,使得边缘提取更加准确。 2. 边缘检测:使用Canny算法或Sobel算子等边缘检测算法,检测图像中的边缘。这里需要根据实际情况调整参数,以确保检测到了纸张边缘。 3. 轮廓检测:根据边缘检测的结果,使用findContours函数检测出图像中的所有轮廓。 4. 提取纸张边框:根据轮廓的特征(例如面积、周长、凸包等),筛选出纸张边框的轮廓。可以根据实际情况调整筛选条件。 5. 裁切摆正:根据纸张边框的四个角点,使用透视变换将原始图像裁切并旋转到水平方向。 代码示例: ```python import cv2 # 读取原始图像 img = cv2.imread('input.jpg') # 灰度化 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化 ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # 降噪 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) binary = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel) # 边缘检测 edges = cv2.Canny(binary, 30, 150) # 轮廓检测 contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 提取纸张边框 paper_contour = None for contour in contours: # 筛选条件:面积、周长、凸包等 area = cv2.contourArea(contour) perimeter = cv2.arcLength(contour, True) hull = cv2.convexHull(contour) solidity = 1.0 * area / cv2.contourArea(hull) if area > 50000 and perimeter > 1000 and solidity > 0.9: paper_contour = contour break # 裁切摆正 if paper_contour is not None: rect = cv2.minAreaRect(paper_contour) box = cv2.boxPoints(rect) box = box.astype(int) cv2.drawContours(img, [box], 0, (0, 0, 255), 2) M = cv2.getPerspectiveTransform(box, np.array([[0, 0], [800, 0], [800, 1100], [0, 1100]], dtype=np.float32)) dst = cv2.warpPerspective(img, M, (800, 1100)) cv2.imshow('result', dst) else: print('No paper found') cv2.waitKey(0) cv2.destroyAllWindows() ``` 上述代码中,使用了Canny算法进行边缘检测,使用findContours函数进行轮廓检测,使用最小外接矩形和透视变换进行裁切摆正。需要注意的是,提取纸张边框的筛选条件需要根据实际情况调整。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小风_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值