0
点赞
收藏
分享

微信扫一扫

Qt车牌识别

毅会 2022-08-16 阅读 39


蓝牌,黄牌,绿牌都能准确识别,颜色识别的方法采用车牌数字识别后,再去截取车牌区域的颜色进行分类识别

Qt车牌识别_opencv


Qt车牌识别_#include_02


Qt车牌识别_opencv_03


具体调用代码如下:

#pragma execution_character_set("utf-8")
#include "mainwindow.h"
#include "qdebug.h"
#include "qpushbutton.h"
#include "QFileDialog"
#include <QLoggingCategory>
#include "qlayout.h"
#include "qlabel.h"
#include "qfile.h"
void drawRect(cv::Mat image,cv::Rect rect)
{
cv::Point p1(rect.x,rect.y);
cv::Point p2(rect.x+rect.width,rect.y+rect.height);
cv::rectangle(image,p1,p2,cv::Scalar(0,255,0),1);
}
void getMaxClass(cv::Mat &probBlob, int *classId, double *classProb)
{
// cv::Mat probMat = probBlob.matRefConst().reshape(1, 1); //reshape the blob to 1x1000 matrix
cv::Point classNumber;

cv::minMaxLoc(probBlob, NULL, classProb, NULL, &classNumber);

*classId = classNumber.x;
}
/*
-----------Levenshtein距离(度量车牌识别效果)------------
编辑距离Edit Distance,又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数;
Levenshtein距离算法可见
@s1 : 字符串1;
@s2 : 字符串2;
*/
template<class T>
static unsigned int levenshtein_distance(const T &s1, const T &s2){
//获取s1、s2的字符长;
const size_t len1 = s1.size(), len2 = s2.size();
//声明col和prevCol辅助计算;
//col记录的是最新的计数情况;
//prevCol记录的是上一轮的计数情况;
std::vector<unsigned int> col(len2 + 1), prevCol(len2 + 1);
//迭代给prevCol赋值;
for (unsigned int i = 0; i < prevCol.size(); i++) prevCol[i] = i;
//迭代比较;扫描两字符串(n*m级的);
for (unsigned int i = 0; i < len1; i++) {
col[0] = i + 1;
//迭代遍历s2[j] in s2;
for (unsigned int j = 0; j < len2; j++)
//比较是否不一样,交换代价最小方式优先;
col[j + 1] = min(
min(prevCol[1 + j] + 1, col[j] + 1),
prevCol[j] + (s1[i] == s2[j] ? 0 : 1));
//col与prevCol交换其内容(swap函数:prevCol的类型要与该vector一样,大小可以不同.);
col.swap(prevCol);
}
//返回结果;
return prevCol[len2];
}

QImage MatToQImage(const Mat& mat)
{
// 8-bits unsigned, NO. OF CHANNELS = 1
if(mat.type() == CV_8UC1)
{
QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
// Set the color table (used to translate colour indexes to qRgb values)
image.setColorCount(256);
for(int i = 0; i < 256; i++)
{
image.setColor(i, qRgb(i, i, i));
}
// Copy input Mat
uchar *pSrc = mat.data;
for(int row = 0; row < mat.rows; row ++)
{
uchar *pDest = image.scanLine(row);
memcpy(pDest, pSrc, mat.cols);
pSrc += mat.step;
}
return image;
}
// 8-bits unsigned, NO. OF CHANNELS = 3
else if(mat.type() == CV_8UC3)
{
// Copy input Mat
const uchar *pSrc = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
return image.rgbSwapped();
}
else if(mat.type() == CV_8UC4)
{
// qDebug() << "CV_8UC4";
// Copy input Mat
const uchar *pSrc = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
return image.copy();
}
else
{
//qDebug() << "ERROR: Mat could not be converted to QImage.";
return QImage();
}
}

/*
-----------测试函数:测试识别准确率------------

*/
void TEST_ACC(){
//声明PipelinePR实例;
pr::PipelinePR prc("model/cascade.xml",
"model/HorizonalFinemapping.prototxt","model/HorizonalFinemapping.caffemodel",
"model/Segmentation.prototxt","model/Segmentation.caffemodel",
"model/CharacterRecognization.prototxt","model/CharacterRecognization.caffemodel",
"model/SegmenationFree-Inception.prototxt","model/SegmenationFree-Inception.caffemodel"
);
//申明文件流;
ifstream file;
//图片路径;
string imagename;
//声明计数变量;
int n = 0,correct = 0,j = 0,sum = 0;
//图片名文本文件路径;
char filename[] = "1.txt";
//图片文件根目录;
string pathh = "/";
//打开图片名文本文件;
file.open(filename, ios::in);
//读取图片名文本文件;
while (!file.eof())
{
//读取一个图片名到imagename;
file >> imagename;
//该图片绝对路径;
string imgpath = pathh + imagename;
//输出信息;
std::cout << "------------------------------------------------" << endl;
cout << "图片名:" << imagename << endl;
//读入图片;
cv::Mat image = cv::imread(imgpath);
//显示图片;
//cv::imshow("image", image);
//cv::waitKey(0);
//申明一个存储该图片车牌信息检测结果的列表,读取结果;
std::vector<pr::PlateInfo> res = prc.RunPiplineAsImage(image,pr::SEGMENTATION_FREE_METHOD);

//置信度变量;
float conf = 0;
//置信度列表;
vector<float> con ;
//车牌名列表;
vector<string> name;
//遍历结果res;
for (auto st : res) {
//置信度大于0.1;
if (st.confidence > 0.1) {
//输出检测信息及置信度;
//std::cout << st.getPlateName() << " " << st.confidence << std::endl;
//加入置信度列表con;
con.push_back(st.confidence);
//加入车牌名列表name;
name.push_back(st.getPlateName());
//置信度综述累计;
//conf += st.confidence;
}
//置信度小于0.1;
else
cout << "no string" << endl;
}
//输出置信度总数;
//std::cout << conf << std::endl;
//置信度列表大小;
int num = con.size();
//置信度最大值变量;
float max = 0;
//声明存储车牌字符、车牌前两个字符、车牌正确的前两个字符的变量;
string platestr, chpr, ch;
//声明度量车牌识别误差的变量;
int diff = 0,dif = 0;
//遍历置信度列表;
for (int i = 0; i < num; i++) {
//寻找最大的置信度下标;
if (con.at(i) > max)
{
//最大置信度max;
max = con.at(i);
//platestr取"最可信"(最大置信度)的结果;
platestr = name.at(i);
}

}
//输出最大置信度;
//cout << "max:"<<max << endl;
//输出车牌字符;
cout << "string:" << platestr << endl;
//车牌前两个字符;
chpr = platestr.substr(0, 2);
//车牌正确的前两个字符的变量;
ch = imagename.substr(0, 2);
//度量距离;
diff = levenshtein_distance(imagename, platestr);
//dif值;
dif = diff - 4;
//输出;
cout << "差距:" <<dif << endl;
//累计;
sum += dif;
//错误计数;
if (ch != chpr) n++;
//正确计数;
if (diff == 0) correct++;
//总数计数;
j++;
}
//计算汉字识别准确率;
float cha = 1 - float(n) / float(j);
//输出;
std::cout << "------------------------------------------------" << endl;
//输出车牌总数;
cout << "车牌总数:" << j << endl;
//输出汉字识别准确率;
cout << "汉字识别准确率:"<<cha << endl;
//计算字符识别准确率;
float chaccuracy = 1 - float(sum - n * 2) /float(j * 8);
//输出;
cout << "字符识别准确率:" << chaccuracy << endl;
}

/*
-----------测试函数:画框------------

*/
PlateInfo TEST_PIPELINE(QString filename){
//声明PipelinePR实例;
pr::PipelinePR prc("model/cascade.xml",
"model/HorizonalFinemapping.prototxt","model/HorizonalFinemapping.caffemodel",
"model/Segmentation.prototxt","model/Segmentation.caffemodel",
"model/CharacterRecognization.prototxt","model/CharacterRecognization.caffemodel",
"model/SegmenationFree-Inception.prototxt","model/SegmenationFree-Inception.caffemodel"
);
//读取一张图片;
PlateInfo retPi;
double confidence=0;
cv::Mat image = cv::imread(filename.toUtf8().data());
//申明一个存储该图片车牌信息检测结果的列表,读取结果;
std::vector<pr::PlateInfo> res = prc.RunPiplineAsImage(image,pr::SEGMENTATION_FREE_METHOD);
//遍历结果;
for(auto st:res) {
//选择置信度大于0.75的结果;
if(st.confidence>0.75) {
//输出结果;
qDebug()<<st.getColorType()<<QString::fromStdString(st.getPlateName()) << "," << st.confidence ;
//矩形框位置;
cv::Rect region = st.getPlateRect();

//绘制框;
cv::rectangle(image,cv::Point(region.x,region.y),cv::Point(region.x+region.width,region.y+region.height),cv::Scalar(255,255,0),2);
if(st.confidence>confidence)
{
//cv::imwrite("carnum.jpg",st.getPlateImage());
confidence=st.confidence;
st.setSrcImage(image);
retPi=st;
}
}
}
//显示结果;
// cv::imshow("image",image);
return retPi ;
}



/*
-----------测试函数:视频流------------

*/
void TEST_CAM()
{
//获取视频;
cv::VideoCapture capture("test1.mp4");
//申明帧变量;
cv::Mat frame;
//声明PipelinePR实例;
pr::PipelinePR prc("model/cascade.xml",
"model/HorizonalFinemapping.prototxt","model/HorizonalFinemapping.caffemodel",
"model/Segmentation.prototxt","model/Segmentation.caffemodel",
"model/CharacterRecognization.prototxt","model/CharacterRecognization.caffemodel",
"model/SegmenationFree-Inception.prototxt","model/SegmenationFree-Inception.caffemodel"
);
//循环读取帧;
while(1) {
//读取下一帧
//异常处理;
if (!capture.read(frame)) {
std::cout << "读取视频失败" << std::endl;
exit(1);
}
//图像旋转;
//cv::transpose(frame,frame);
//图像翻转;
//cv::flip(frame,frame,2);
//大小调整;
//cv::resize(frame,frame,cv::Size(frame.cols/2,frame.rows/2));
//识别结果;
std::vector<pr::PlateInfo> res = prc.RunPiplineAsImage(frame,pr::SEGMENTATION_FREE_METHOD);
//遍历识别结果
for(auto st:res) {
if(st.confidence>0.75) {
//输出结果;
std::cout << st.getPlateName() << " " << st.confidence << std::endl;
//矩形框位置;
cv::Rect region = st.getPlateRect();
//绘制框;
cv::rectangle(frame,cv::Point(region.x,region.y),cv::Point(region.x+region.width,region.y+region.height),cv::Scalar(255,255,0),2);
}
}
//显示;
cv::imshow("image",frame);
//等待;
cv::waitKey(1);
}
}

MainWindow::MainWindow(QWidget *parent) :
QWidget(parent)
{
setMinimumSize(960,600);
QLoggingCategory::setFilterRules(QStringLiteral("qt.speech.tts=true \n qt.speech.tts.*=true"));

QPushButton *btn=new QPushButton(this);
btn->setText("打开图像");
btn->setFixedSize(80,24);
btn->move(100,100);
btn->show();
connect(btn,SIGNAL(clicked()),this,SLOT(slot_openFile()));
m_carImage=new ImageWidget(this);
m_carNumImage=new ImageWidget(this);
m_carNumImage->setFixedSize(140,36);
m_carNum=new QLineEdit(this);
m_carNum->setFixedWidth(100);
m_carType=new QLineEdit(this);
m_carType->setFixedWidth(100);
QVBoxLayout *vl=new QVBoxLayout();
setLayout(vl);
QHBoxLayout *hl=new QHBoxLayout();
hl->addStretch();
hl->addWidget(btn);
QLabel *lab1=new QLabel("车牌号码:",this);
QLabel *lab2=new QLabel("车牌类型:",this);
hl->addWidget(lab1);
hl->addWidget(m_carNum);
hl->addWidget(lab2);
hl->addWidget(m_carType);
hl->addWidget(m_carNumImage);
hl->addStretch();
vl->addLayout(hl);
vl->addWidget(m_carImage,Qt::AlignHCenter);
}
void MainWindow::slot_openFile()
{
qDebug()<<"slot_openFile";
QString filename=QFileDialog::getOpenFileName(this, QString("选择图片文件"), "", QString("图片文件格式(*.jpg *.png *.jpeg *. bmp)"));
qDebug()<<"filename == "<<filename;
if(filename.length()>0)
{
m_carNum->setText("");
m_carType->setText("");
m_carImage->setImage(QImage());
m_carNumImage->setImage(QImage());

PlateInfo pi= TEST_PIPELINE(filename);
qDebug()<<"PlateInfo == ";
if(pi.getPlateName().length()>0)
{
//输出结果;
QString txt=QString::fromStdString(pi.getPlateName());
m_carNum->setText(txt);
m_carType->setText(pi.getColorType());
m_carImage->setImage(MatToQImage(pi.getSrcImage()));
m_carNumImage->setImage(MatToQImage(pi.getPlateImage()));
}
}
}
MainWindow::~MainWindow()
{
}

Qt车牌识别_i++_04


Qt车牌识别_#include_05


Qt车牌识别_ide_06


Qt车牌识别_i++_07



举报

相关推荐

0 条评论