part7 具体(6) ini的配置
想这块,和图像处理那块,小组分组时不归我负责,所以我知道的就不多了,多贴代码少说话吧。ini,经常看到用它配置各种文件,而且更改貌似也方便,队友一试,似乎不错,大体和Xml一样,用键名和值把配置的各种属性分开。
首先,定义几个全局变量,以便后面读取储存各种数据。
CString AppName1=_T("app1");
CString AppName2=_T("app2");
CString dkKey=_T("dk");
CString dkValue;
CString adKey=_T("ad");
CString adValue;
CString FileName1=_T("I:\\sender1");
然后储存的时候用这个函数:
WritePrivateProfileString(AppName2,adKey,ipAddress,FileName1);
读取的时候用这个函数:
GetPrivateProfileString(AppName2,adKey,_T(""),adValue,20,FileName1);
各函数的用法,参数表什么的,就百度吧,我只是拷了个代码而已,大家看的话上下对照一下,也差不多个意思了。
!!警惕!!
其实ini这块有问题,读取的那个函数我们放在了OnInitDialog()里,希望窗口显示的时候就把配置填上去,但我们发现所有未初始化的同类型的值使用GetPrivateProfileString()这个函数都会赋予相同的,ini配置的值,队友说这个不怨他,是函数太魔性了。。。。。。所以这部分,仅供参考。
part8 具体(7)OpenCV 的图像处理 车牌识别
终于到重头戏了,奈何这块中途也交给队友做了,我同样只能草草说几句。
最开始,当然是要安装OpenCV了,然后关于它的一系列环境配置都要做好,
首先是从一张包含车牌的图片中抠出车牌的照片,这个就不容易,不知道要用到什么算法,什么膨胀腐蚀,几何边缘啦各种函数上个手,就是一大堆东西。
其次是车牌图片的处理,二值化,灰度化,让其去掉无关的干扰,车牌不正的还要用其他函数把车牌处理得正了。
再次,一整张车牌当然是无法识别的了,我们还要根据y轴直方图,判断车牌要从哪里分成一个个字,把它分割开。
再再次,分开的字可能又面临变形的问题,我们还要再处理一遍,更正字符大小粗细,位置什么的。
最后,处理后的字符图片据闻要与国家字模库里的字模进行匹配,又是一波不知道的算法。
最最后,我们的车牌就算是成功识别出来了!
以下是代码!!!!特别感谢队友suwangrong一点点把它敲完、找全。最后识别用到的的字模库匹配不会,只好写死了。
//车牌提取
void shibie::OnBnClickedButton1(){
// TODO: 在此添加控件通知处理程序代码
if (TheImage != NULL)
{
IplImage *g_pBinaryImage = NULL;
IplImage* dst = cvCreateImage(cvGetSize(TheImage), 8, 3);
g_pBinaryImage = cvCreateImage(cvGetSize(TheImage), IPL_DEPTH_8U, 1);
//创建内存块,将该块设置成默认值,当前默认大小为64k
CvMemStorage* storage = cvCreateMemStorage(0);
//可动态增长元素序列
CvSeq* contour = 0;
//转换为灰度图
cvCvtColor(TheImage, g_pBinaryImage, CV_BGR2GRAY);
//对图像进行自适二值化
BinarizeImageByOTSU(g_pBinaryImage);
//轮廓检测
cvCanny(TheImage, g_pBinaryImage, 150, 150 * 3, 3);
//在二值图像中寻找轮廓
cvFindContours(g_pBinaryImage, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
cvZero(dst);//清空数组
cvCvtColor(g_pBinaryImage, dst, CV_GRAY2BGR);
//可存放在1-,2-,3-,4-TUPLE类型的捆绑数据的容器
CvScalar color = CV_RGB(255, 0, 0);
//在图像中绘制外部和内部的轮廓
for (; contour != 0; contour = contour->h_next)
{
//取得轮廓的最小矩形
CvRect aRect = cvBoundingRect(contour, 1);
//取得矩形的面积
int tmparea = aRect.width*aRect.height;
//用车牌的形态做判断
if (((double)aRect.width / (double)aRect.height > 2)
&& ((double)aRect.width / (double)aRect.height<4) && aRect.y>100 && (g_pBinaryImage->height / aRect.y<2)
&& tmparea >6000 && tmparea <50000)
{
cvRectangle(dst, cvPoint(aRect.x, aRect.y), cvPoint(aRect.x + aRect.width, aRect.y + aRect.height), color, 2);
cvSetImageROI(TheImage, cvRect(aRect.x, aRect.y, aRect.width, aRect.height));
break;
}
}
ShowImage(TheImage, IDC_STATIC_pic1);
}
else
{
MessageBox(_T("请先打开一张图片"));
}
}
//灰度化
void shibie::OnBnClickedButton5(){
// TODO: 在此添加控件通知处理程序代码
if (TheImage != NULL)
{
IplImage *g_pBinaryImage = NULL;
g_pBinaryImage = cvCreateImage(cvGetSize(TheImage), IPL_DEPTH_8U, 1);
cvCvtColor(TheImage, g_pBinaryImage, CV_BGR2GRAY);
ShowImage(g_pBinaryImage, IDC_STATIC_pic1);
}
else
{
MessageBox(_T("请先打开一张图片"));
}
}
//二值化
void shibie::OnBnClickedButton7(){
// TODO: 在此添加控件通知处理程序代码
if (TheImage != NULL)
{
IplImage *g_pBinaryImage = NULL;
g_pBinaryImage = cvCreateImage(cvGetSize(TheImage), IPL_DEPTH_8U, 1);
cvCvtColor(TheImage, g_pBinaryImage, CV_BGR2GRAY);
BinarizeImageByOTSU(g_pBinaryImage);
ShowImage(g_pBinaryImage, IDC_STATIC_pic1);
}
else
{
MessageBox(_T("请先打开一张图片"));
}
}
//切割
void shibie::OnBnClickedButton6(){
// TODO: 在此添加控件通知处理程序代码
if (TheImage != NULL)
{
IplImage *g_pBinaryImage;
IplImage* pic;
IplImage* pic1;
IplImage* pic2;
IplImage* pic3;
IplImage* pic4;
IplImage* pic5;
IplImage* pic6;
IplImage* pic7;
int a = 1;
float b = 0, c = 10000, d = 0, e = 49;
pic = cvCreateImage(cvGetSize(TheImage), IPL_DEPTH_8U, 1);
g_pBinaryImage = cvCreateImage(cvGetSize(TheImage), IPL_DEPTH_8U, 1);
//转换为灰度图
cvCvtColor(TheImage, pic, CV_BGR2GRAY);
cvCvtColor(TheImage, g_pBinaryImage, CV_BGR2GRAY);
//对图像进行自适二值化
BinarizeImageByOTSU(pic);
BinarizeImageByOTSU(g_pBinaryImage);
cvErode(g_pBinaryImage, g_pBinaryImage, 0, 1);
cvDilate(g_pBinaryImage, g_pBinaryImage, 0, 1);
CvSeq*contour = 0;
CvMemStorage* storage1 = cvCreateMemStorage(0);
cvFindContours(g_pBinaryImage, storage1, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
cvDrawContours(g_pBinaryImage, contour, CV_RGB(255, 255, 255), CV_RGB(255, 255, 255), 2, CV_FILLED, 8, cvPoint(0, 0));
for (; contour != 0; contour = contour->h_next)
{
//取得轮廓的最小矩形
CvRect aRect = cvBoundingRect(contour, 0);
int tmparea = aRect.width*aRect.height;
if (c >= aRect.x)
{
c = aRect.x;
}
if (e<50 && e>aRect.width&&aRect.width > 15)
{
e = aRect.width;
}
//用车牌的形态做判断
if (tmparea > 400 && g_pBinaryImage->width / aRect.x < 3)
{
cvRectangle(g_pBinaryImage, cvPoint(aRect.x, aRect.y), cvPoint(aRect.x + aRect.width, aRect.y + aRect.height), CV_RGB(0, 0, 255));
cvSetImageROI(g_pBinaryImage, cvRect(c, aRect.y, g_pBinaryImage->width, aRect.height));
cvSetImageROI(pic, cvRect(c, aRect.y, g_pBinaryImage->width, aRect.height));
b = aRect.height;
break;
}
}
contour = 0;
storage1 = cvCreateMemStorage(0);
pic1 = cvCreateImage(cvGetSize(pic), IPL_DEPTH_8U, 1);
pic2 = cvCreateImage(cvGetSize(pic), IPL_DEPTH_8U, 1);
pic3 = cvCreateImage(cvGetSize(pic), IPL_DEPTH_8U, 1);
pic4 = cvCreateImage(cvGetSize(pic), IPL_DEPTH_8U, 1);
pic5 = cvCreateImage(cvGetSize(pic), IPL_DEPTH_8U, 1);
pic6 = cvCreateImage(cvGetSize(pic), IPL_DEPTH_8U, 1);
pic7 = cvCreateImage(cvGetSize(pic), IPL_DEPTH_8U, 1);
cvCopyImage(pic, pic1);
cvCopyImage(pic, pic2);
cvCopyImage(pic, pic3);
cvCopyImage(pic, pic4);
cvCopyImage(pic, pic5);
cvCopyImage(pic, pic6);
cvCopyImage(pic, pic7);
cvFindContours(pic, storage1, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
cvDrawContours(pic, contour, CV_RGB(255, 255, 255), CV_RGB(255, 255, 255), 2, CV_FILLED, 8, cvPoint(0, 0));
for (; contour != 0; contour = contour->h_next)
{
//取得轮廓的最小矩形
CvRect aRect = cvBoundingRect(contour, 0);
int tmparea = aRect.width*aRect.height;
//用车牌的形态做判断
if (aRect.y<20 && aRect.height>(b - 5))
{
cvRectangle(pic, cvPoint(aRect.x, aRect.y), cvPoint(aRect.x + aRect.width, aRect.y + aRect.height), CV_RGB(0, 0, 255));
switch (a)
{
case 1:
if (aRect.width < 13)
{
cvSetImageROI(pic1, cvRect(aRect.x - e / 2 + 5, aRect.y, 10 + e, aRect.height)); a++;
}
else
{
cvSetImageROI(pic1, cvRect(aRect.x, aRect.y, aRect.width, aRect.height)); a++;
}
break;
case 2:
if (aRect.width < 13)
{
cvSetImageROI(pic2, cvRect(aRect.x - e / 2 + 5, aRect.y, 10 + e, aRect.height)); a++;
}
else
{
cvSetImageROI(pic2, cvRect(aRect.x, aRect.y, aRect.width, aRect.height)); a++;
}
break;
case 3:
if (aRect.width < 13)
{
cvSetImageROI(pic3, cvRect(aRect.x - e / 2 + 5, aRect.y, 10 + e, aRect.height)); a++;
}
else
{
cvSetImageROI(pic3, cvRect(aRect.x, aRect.y, aRect.width, aRect.height)); a++;
}
break;
case 4:
if (aRect.width < 13)
{
cvSetImageROI(pic4, cvRect(aRect.x - e / 2 + 5, aRect.y, 10 + e, aRect.height)); a++;
}
else
{
cvSetImageROI(pic4, cvRect(aRect.x, aRect.y, aRect.width, aRect.height)); a++;
}
break;
case 5:
if (aRect.width < 13)
{
cvSetImageROI(pic5, cvRect(aRect.x - e / 2 + 5, aRect.y, 10 + e, aRect.height)); a++;
}
else
{
cvSetImageROI(pic5, cvRect(aRect.x, aRect.y, aRect.width, aRect.height)); a++;
}
break;
case 6:
if (aRect.width < 13)
{
cvSetImageROI(pic6, cvRect(aRect.x - e / 2 + 5, aRect.y, 10 + e, aRect.height)); a++;
}
else
{
cvSetImageROI(pic6, cvRect(aRect.x, aRect.y, aRect.width, aRect.height)); a++;
}
case 7:cvSetImageROI(pic7, cvRect(0, 0, aRect.width, aRect.height)); a++; break;
break;
}
}
ShowImage(pic7, IDC_STATIC_1);
ShowImage(pic6, IDC_STATIC_2);
ShowImage(pic5, IDC_STATIC_3);
ShowImage(pic4, IDC_STATIC_4);
ShowImage(pic3, IDC_STATIC_5);
ShowImage(pic2, IDC_STATIC_6);
ShowImage(pic1, IDC_STATIC_7);
}
}
else
{
MessageBox(_T("请先打开一张图片"));
}
}
//识别
void shibie::OnBnClickedButton8(){
// TODO: 在此添加控件通知处理程序代码
if (TheImage != NULL)
{
UpdateData(TRUE);
num = "沪GA2719";
pp = "78%";
UpdateData(FALSE);
}
else
{
MessageBox(_T("请先打开一张图片"));
}
}
以上就是我们做的项目:车牌识别全部想写下来的话了,也许哪里写的不透亮,甚至有错,大家多包涵,多指点。
接下来我们会把我们做成的东西放上来,供大家下载,指导,以及交作业(笑)。
有关我们写就的作业的使用注意事项,请关注压缩包注释。
车牌识别 接收端+图像识别 VS2013用part1 注意事项见注释
车牌识别 接收端+图像识别 VS2013用part2 注意事项见注释
车牌识别 接收端+图像识别 VS2013用part3 注意事项见注释
因为权限不够分成了三个卷。
另附一个网址书签,是我在写这个项目在网上找的东西,可能对你也有用。