opencv——识别A4纸

小编这篇给大家带来的是如何用opencv在视野中识别出A4纸或者是某一个具体的靶标什么的,同样的算法改改可以用来识别其他的形状的物体,先来看看实际的效果:

由于小编是在虚拟机下调用摄像头出现了一些问题,还没有试试连续过程中的识别情况,等摄像头到了,小编会再后续中测试。
在程序开始之前我们先梳理一下解决这个问题的流程:
1、图像预处理(这里考虑到处理速度问题采用的是高斯滤波)
2、边缘检测(本文采用的canny算子)
3、膨胀(尽量使边缘闭合)
4、寻找A4边框(采用的是findContours算法)
5、对findContours识别出来的轮廓进行排除得到我们需要的轮廓,这是最为核心的一步。譬如本文是筛选类似A4纸书本这样的框,采用的方法是先对得到的轮廓进行凸包拟合,然后以四边形和每个夹角大于60作为这样的一个初步筛选。然后从筛选出来的轮廓中选择最大的那个就是我们想要的了。(注:由于本文是一个demo,筛选条件比较简单,读者结合自己的应用常见和识别对象可以利用譬如直方图统计这样的增加筛选成功率)
6、得到满足筛选条件的最大轮廓的四个顶点(方便后面做透视校正,小编会在后面陆续写出分享)
7、绘出我们的轮廓
下面给出具体代码,有以问的欢迎留言交流:
#include
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp> //图像处理头文件
#include <cv.h>
#include <highgui.h>
#include
using namespace cv;
using namespace std;

//根据三个点计算中间那个点的夹角,这里是用三角变换,感兴趣的可以求一下公式的推导 pt1 pt0 pt2
double getAngle(cv::Point pt1, cv::Point pt2, cv::Point pt0)
{
double dx1 = pt1.x - pt0.x;
double dy1 = pt1.y - pt0.y;
double dx2 = pt2.x - pt0.x;
double dy2 = pt2.y - pt0.y;
return (dx1dx2 + dy1dy2)/sqrt((dx1dx1 + dy1dy1)(dx2dx2 + dy2*dy2) + 1e-10);
}

//寻找最大边框
int findLargestSquare(const vector<vectorcv::Point >& squares, vectorcv::Point& biggest_square)
{
if (!squares.size()) return -1;
int max_width = 0;
int max_height = 0;
int max_square_idx = 0;
for (int i = 0; i < squares.size(); i++)
{
cv::Rect rectangle = boundingRect(Mat(squares[i]));
if ((rectangle.width >= max_width) && (rectangle.height >= max_height))
{
max_width = rectangle.width;
max_height = rectangle.height;
max_square_idx = i;
}
}
biggest_square = squares[max_square_idx];
return max_square_idx;
}

//主函数,小编这里反省一下,没有把一些函数封装起来,显得比较乱,小编建议大家养成把处理得函数都封装起来,主函数就不会像小编这样看上去很乱了。
int main(int argc, char *argv[])
{
Mat src,dst,gray,binarization,open,dilate_img,gauss_img,edges_img;
src = imread("/home/shangbinbin/opencv_linux_test/test3/4.jpg");
//处理为灰度图
cvtColor(src,gray,CV_BGR2GRAY);
//高斯滤波
GaussianBlur(gray,gauss_img,Size(3,3),2,2);
//边缘检测
Canny(gauss_img,edges_img,50,150,3);
//膨胀
dilate(edges_img, dilate_img, Mat(), cv::Point(-1, -1), 3, 1, 1);
//定义容器类型得变量,不太明白得可以看看C++的容器这一部分知识
vector<vectorcv::Point > contours, squares, hulls;

//寻找出所有闭合的边框
findContours(dilate_img, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);

vectorcv::Point hull, approx;
//筛选边框
for (int i = 0; i < contours.size(); i++)
{
//获得轮廓的凸包
convexHull(contours[i], hull);
//多边形拟合凸包边框(此时的拟合的精度较低)
//arcLength得到轮廓的长度
approxPolyDP(Mat(hull), approx, arcLength(Mat(hull), true)*0.02, true);
//筛选出四边形的各个角度都接近直角的凸四边形
if (approx.size() ==4 && isContourConvex(Mat(approx))&& fabs(contourArea(Mat(approx))) < 1166400)
{
double maxCosine = 0;
for (int j = 2; j < 5; j++)
{
double cosine = fabs(getAngle(approx[j%4], approx[j-2], approx[j-1]));
maxCosine = MAX(maxCosine, cosine);
}
//角度大概72度
if (maxCosine < 0.4)
{
squares.push_back(approx);
hulls.push_back(hull);
}

           }

}
vectorcv::Point largest_square;
//找出外接矩形最大的四边形
int idex = findLargestSquare(squares, largest_square);
//画图
for (int i = 0; i < 4; i++)
{
// circle(src,squares[idex][i],5,Scalar(0,0,255), 5);
if(i<3)
{
line(src, squares[idex][i], squares[idex][i+1], Scalar(0,0,255), 5);
}
else
line(src, squares[idex][3], squares[idex][0], Scalar(0,0,255), 5);
}
//显示出来
namedWindow(“draw”, CV_WINDOW_NORMAL);
imshow(“draw”,src);
waitKey(0);
return 0;
}
关注微信公众号share space,有超多资料和实用教程等你来。

OpenCV是一个非常强大的计算机视觉库,可以用于图像处理、目标检测、人脸识别等多种场景。对于A4识别,可以采用以下步骤: 1. 读取视频流:使用OpenCV中的VideoCapture类读取视频流。 2. 预处理:对每一帧图像进行预处理,包括灰度化、高斯模糊、边缘检测等。 3. 寻找轮廓:通过Canny算法找到图像中的所有轮廓,并筛选出符合条件的轮廓。 4. 计算四边形:对符合条件的轮廓进行透视变换,得到A4的矩形区域。 5. 显示结果:将结果显示在图像上,并输出相关信息。 下面是示例代码: ```python import cv2 import numpy as np # 读取视频流 cap = cv2.VideoCapture(0) while True: # 读取一帧图像 ret, frame = cap.read() if not ret: break # 预处理 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5, 5), 0) canny = cv2.Canny(blur, 50, 200) # 寻找轮廓 contours, hierarchy = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: area = cv2.contourArea(cnt) if area < 1000 or area > 100000: continue approx = cv2.approxPolyDP(cnt, 0.02 * cv2.arcLength(cnt, True), True) if len(approx) != 4: continue rect = cv2.minAreaRect(cnt) box = cv2.boxPoints(rect) box = np.int0(box) # 绘制四边形 cv2.drawContours(frame, [box], 0, (0, 255, 0), 3) # 显示结果 cv2.imshow('frame', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值