前言
本人c++小白,主要是做android这块的,底层涉及甚少,c++上学的时候自学过一点,还算有点基础。
之前有提过身份证识别的需求,考虑到用三方的需要收费,于是就自己研究下身份证识别喽。
有2个思路:
- 安卓ndk层调用opencv,手机识别
- c++实现,java调c,java封装接口,供手机调用
有个想法:就是用vs集成opencv,做个可以识别身份证的可执行文件.exe的东东,然后用java调用exe,封装一个http接口,android端上传身份证照片,后台识别返回结果,不知道能不能做,先慢慢来了
步骤1 配置开发环境##
参考大神博客:VS2013+OpenCV开源库使用入门
步骤2
了解身份证识别的算法:(个人理解)
百度找的图片
-
图片灰度化:就是把彩色照片变为黑白照片,为什么要这样做呢?颜色是rgb3种颜色组成的,变为黑白就是简化颜色矩阵,提高运算速率。效果图:
-
二值化:就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果,就是有个阀值,这里取120到220
-
腐蚀:腐蚀就是把像素点放大,如把x,y坐标都扩大15个像素,这样原来的一个点就变为了一个像素块,这样做就是为了把文字连成一块,这样可以好识别
-
轮廓检测:对腐蚀后的图片进行轮廓检测,用到findContours函数,分割为多块
下面贴出个人调试源码
// cv.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
#include<opencv2\opencv.hpp>
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
Mat img = imread("card.png");
namedWindow("原图");
imshow("原图", img);
Mat temp, temp2, temp3;
//灰度化
cvtColor(img, temp, COLOR_BGR2GRAY);
cvtColor(temp, img, COLOR_GRAY2BGRA);
namedWindow("灰度化");
imshow("灰度化", temp);
//二值化
threshold(temp, temp2, 100, 200, CV_THRESH_BINARY);
namedWindow("二值化");
imshow("二值化", temp2);
//腐蚀
Mat erodeElement = getStructuringElement(MORPH_RECT, Size(13, 13));
erode(temp2, temp3, erodeElement);
namedWindow("腐蚀");
imshow("腐蚀", temp3);
//轮廓检测
vector<vector<Point> > contours; //定义一个容器来存储所有检测到的轮廊
vector<Vec4i> hierarchy;
//轮廓检测函数
Mat conv(temp3.size(), CV_8UC1);
temp3.convertTo(conv, CV_8UC1);
findContours(conv, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, cvPoint(0, 0));
int index = 0;
long max_Index = static_cast<long>(contours.size());
if (index < max_Index - 1) {
++index;
}
//取出身份证号码区域
vector<Rect> rects;
Rect numberRect = Rect(0, 0, 0, 0);
vector<vector<Point> >::const_iterator itContours = contours.begin();
for (int i = 0; i <max_Index; ++i) {
Rect rect = boundingRect(itContours[i]);
numberRect = rect;
Mat dst(numberRect.height, numberRect.width, CV_8UC4, numberRect.area());
dst = img(numberRect);
for (int i = 0; i <max_Index; ++i) {
Rect rect = boundingRect(itContours[i]);
numberRect = rect;
Mat dst(numberRect.height, numberRect.width, CV_8UC4, numberRect.area());
dst = img(numberRect);
if (rect.y > img.rows / 2 && rect.width / rect.height > 6){
imshow("身份证号:", dst);
}
}
}
waitKey(0);
cout << CV_MAJOR_VERSION << endl;
return 0;
}
总结
c这块小白一枚,我再去看看c++基础,opencv也是刚看,如果错误,请各位大神指点!