#include "widget.h"
#include "ui_widget.h"
#include <QTimer>
#include <QString>
#include <QFileDialog>
#include <QMessageBox>
#include <string>
#include <QDebug>
#include <stdlib.h>
widget::widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::widget)
{
ui->setupUi(this);
}
widget::~widget()
{
delete ui;
}
void widget::on_pushButton_clicked()
{
QString s = QFileDialog::getOpenFileName(this , "打开图片文件","/",
tr("Images (*.png *.xpm *.jpg)"));
std::string str = s.toStdString();
const char* ch = str.c_str(); //路径不能包含中文,否则用imread打不开
if(s.isEmpty())
{
return;
}
else
{
QImage* img=new QImage;
if(! ( img->load(s) ) ) //加载图像
{
QMessageBox::information(this,
tr("打开图像失败"),
tr("打开图像失败!"));
delete img;
return;
}
QImage* imgScaled = new QImage; //更改图片分辨率
*imgScaled = img->scaled(480,
360,
Qt::KeepAspectRatio); //换为Qt::IgnoreAspectRatio,则一律变更
ui->label_display->resize(imgScaled->size());
ui->label_display->setPixmap(QPixmap::fromImage(*imgScaled));
imgSrc = imread(ch ,1); //使用打开的文件对话框获得的路径,由imread读出
}
}
void widget::on_pushButton_2_clicked()
{
//Mat imgSrc_test = imread("E:/PracticeOfQt/Id_recognition/id_cardBai.jpg" ,1); //用于测试,实际应用只需将下面替换成imgSrc
Mat imgRplane = getRplane(imgSrc); //获得原始图像R分量
vector <RotatedRect> rects;
posDetect(imgRplane ,rects); //获得身份证号码区域
Mat outputMat;
normalPosArea(imgRplane ,rects[0],outputMat); //获得身份证号码字符矩阵
vector<Mat> char_mat; //获得切割得的字符矩阵
char_segment(outputMat , char_mat);
//getAnnXML(); //该函数只需执行一次,获得训练矩阵和标签矩阵,保存于xml文件中
CvANN_MLP ann;
ann_train(ann, 10, 24); //10为输出层结点,也等于输出的类别,24为隐藏层结点
vector<int> char_result;
classify( ann ,char_mat ,char_result);
getParityBit(char_result); //最后一位易出错,直接由前17位计算最后一位
//设置界面信息
if(char_result[16]%2 == 1) //根据倒数第2位区分男女
{
ui->radioButton->setChecked(true);
}
else
ui->radioButton_2->setChecked(true);
QString id = "";
for(int i = 0; i < char_result.size();++i)
{
if (char_result[i] == 10)
id += "X";
else
id += QString::number(char_result[i], 10); //将int转换为Qstring
}
ui->lineEdit_2->setText(id);
QString birthday;
for(int i = 6; i < 14;++i)
birthday += id[i];
ui->lineEdit->setText(birthday);
}
Mat widget::getRplane(const Mat &in)
{
vector<Mat> splitBGR(in.channels()); //容器大小为通道数3
split(in,splitBGR);
//return splitBGR[2]; //R分量
if(in.cols > 700 |in.cols >600)
{
Mat resizeR( 450,600 , CV_8UC1);
cv::resize( splitBGR[2] ,resizeR ,resizeR.size());
return resizeR;
}
else
return splitBGR[2];
}
void widget::OstuBeresenThreshold(const Mat &in, Mat &out) //输入为单通道
{
double ostu_T = threshold(in , out, 0,255 ,CV_THRESH_OTSU); //otsu获得全局阈值
double min;
double max;
minMaxIdx(in,&min,&max);
const double CI = 0.12;
double beta = CI*(max - min +1)/128;
double beta_lowT = (1-beta)*ostu_T;
double beta_highT = (1+beta)*ostu_T;
Mat doubleMatIn;
in.copyTo(doubleMatIn);
int rows = doubleMatIn.rows;
int cols = doubleMatIn.cols;
double Tbn;
for( int i = 0; i < rows; ++i)
{
//获取第 i行首像素指针
uchar * p = doubleMatIn.ptr<uchar>(i);
uchar *outPtr = out.ptr<uchar>(i);
//对第i 行的每个像素(byte)操作
for( int j = 0; j < cols; ++j )
{
if(i <2 | i>rows - 3 | j<2 | j>rows - 3)
{
if( p[j] <= beta_lowT )
outPtr[j] = 0;
else
outPtr[j] = 255;
}
else
{
Tbn = sum(doubleMatIn(Rect(i-2,j-2,5,5)))[0]/25 ; //窗口大小25*25
if( p[j] < beta_lowT | (p[j] < Tbn && (beta_lowT <= p[j] && p[j] >= beta_highT)))
outPtr[j] = 0;
if( p[j] > beta_highT | (p[j] >= Tbn && (beta_lowT <= p[j] && p[j] >= beta_highT)))
outPtr[j] = 255;
}
}
}
}
void widget::posDetect(const Mat &in, vector<RotatedRect> & rects)
{
Mat threshold_R;
OstuBeresenThreshold(in ,threshold_R ); //二值化
Mat imgInv(in.size(),in.type(),cv::Scalar(255));
Mat threshold_Inv = imgInv - threshold_R; //黑白色反转,即背景为黑色
Mat element = getStructuringElement(MORPH_RECT ,Size(15 ,3)); //闭形态学的结构元素
morphologyEx(threshold_Inv ,threshold_Inv,CV_MOP_CLOSE,element);
vector< vector <Point> > contours;
findContours(threshold_Inv ,contours,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//只检测外轮廓
//对候选的轮廓进行进一步筛选
vector< vector <Point> > ::iterator itc = contours.begin();
while( itc != contours.end())
{
RotatedRect mr = minAreaRect(Mat( *itc )); //返回每个轮廓的最小有界矩形区域
if(!isEligible(mr)) //判断矩形轮廓是否符合要求
{
itc = contours.erase(itc);
}
else
{
rects.push_back(mr);
++itc;
}
}
//测试是否找到了号码区域
// Mat out;
// in.copyTo(out);
// Point2f vertices[4];
// rects[0].points(vertices);
// for (int i = 0; i < 4; i++)
// line(out, vertices[i], vertices[(i+1)%4], Scalar(0,0,0));//画黑色线条
// imshow("Test_Rplane" ,out);
// waitKey(0);
}
bool widget::isEligible(const RotatedRect &candidate)
{
float error = 0.2;
const float aspect = 4.5/0.3; //长宽比
int min = 10*aspect*10; //最小区域
int max = 50*aspect*50; //最大区域
float rmin = aspect - aspect*error; //考虑误差后的最小长宽比
float rmax = aspect + aspect*error; //考虑误差后的最大长宽比
int area = candidate.size.height * candidate.size.width;
float r = (float)candidate.size.width/(float)candidate.size.height;
if(r <1)
r = 1/r;
if( (area < min || area > max) || (r< rmin || r > rmax) ) //满足该条件才认为该candidate为车牌区域
return false;
else
return true;
}
void widget::normalPosArea(const Mat &intputImg, RotatedRect &rects_optimal, Mat& output_area)
{
float r,angle;
angle = rects_optimal.angle;
r = (float)rects_optimal.size.width / (float) (float)rects_optimal.size.height;
if(r<1)
angle = 90 + angle;
Mat rotmat = getRotationMatrix2D(rects_optimal.center , angle,1);//获得变形矩阵对象
Mat img_rotated;
warpAffine(intputImg ,img_rotated,rotmat, intputImg.size(),CV_INTER_CUBIC);
//裁剪图像
Size rect_size = rects_optimal.size;
if(r<1)
std::swap(rect_size.width, rect_size.height);
Mat img_crop;
getRectSubPix(img_rotated ,rect_size,rects_optimal.center , img_crop );
//用光照直方图调整所有裁剪得到的图像,使具有相同宽度�
没有合适的资源?快使用搜索试试~ 我知道了~
基于Qt和opencv的身份证号码识别系统
共573个文件
png:550个
jpg:14个
cpp:2个
5星 · 超过95%的资源 需积分: 47 1.3k 下载量 128 浏览量
2016-05-24
22:13:39
上传
评论 60
收藏 2.76MB RAR 举报
温馨提示
本文主要实现了对身份证图片上身份证号码的自动识别,在Qt平台上使用opencv进行图像处理,并绘制简单的用户界面,设计了一个基于Qt和opencv的身份证号码识别系统。
资源推荐
资源详情
资源评论
收起资源包目录
基于Qt和opencv的身份证号码识别系统 (573个子文件)
widget.cpp 15KB
main.cpp 336B
widget.h 1KB
id_card002.jpg 274KB
id_card8.jpg 185KB
id_card003.jpg 181KB
id_card001.jpg 175KB
id_card004.jpg 148KB
id_card14.jpg 106KB
id_card7.jpg 41KB
id_card.jpg 40KB
id_card4.jpg 34KB
id_card10.jpg 28KB
id_card6.jpg 26KB
id_card9.jpg 24KB
id_card2.jpg 16KB
id_card5.jpg 16KB
基于图像处理和模式识别的身份证识别系统设计与实现.pdf 1.35MB
8 (50).png 593B
5 (2).png 575B
7 (1).png 560B
5 (4).png 550B
10 (41).png 548B
5 (17).png 532B
10 (21).png 532B
10 (44).png 516B
7 (18).png 496B
10 (14).png 488B
10 (4).png 488B
3 (9).png 484B
9 (30).png 472B
0 (11).png 468B
10 (28).png 468B
6 (11).png 467B
7 (3).png 466B
0 (42).png 466B
7 (7).png 462B
8 (47).png 462B
10 (48).png 458B
8 (12).png 453B
6 (6).png 452B
9 (7).png 452B
10 (35).png 452B
9 (8).png 451B
9 (25).png 451B
0 (41).png 448B
9 (19).png 446B
10 (19).png 446B
9 (29).png 445B
6 (9).png 443B
6 (3).png 443B
6 (5).png 443B
6 (16).png 443B
9 (16).png 443B
3 (8).png 443B
6 (26).png 443B
8 (3).png 443B
10 (6).png 443B
6 (34).png 442B
8 (11).png 440B
2 (34).png 438B
6 (35).png 437B
3 (20).png 437B
9 (15).png 437B
8 (48).png 437B
10 (46).png 437B
6 (38).png 436B
0 (49).png 436B
8 (30).png 436B
4 (31).png 435B
0 (34).png 435B
9 (14).png 434B
7 (22).png 434B
9 (42).png 433B
0 (10).png 433B
9 (28).png 432B
8 (43).png 432B
9 (23).png 431B
9 (24).png 431B
7 (6).png 431B
6 (45).png 430B
9 (22).png 429B
9 (31).png 429B
9 (5).png 429B
6 (17).png 428B
6 (14).png 428B
4 (4).png 428B
4 (5).png 428B
5 (18).png 428B
5 (13).png 428B
0 (37).png 428B
8 (23).png 428B
8 (7).png 428B
10 (7).png 428B
0 (13).png 427B
3 (38).png 426B
2 (49).png 426B
8 (32).png 426B
0 (48).png 426B
0 (16).png 425B
共 573 条
- 1
- 2
- 3
- 4
- 5
- 6
ForeverYang2015
- 粉丝: 2936
- 资源: 11
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
- 4
- 5
- 6
前往页