图像处理之简单的纸牌识别

vs2015 MFC环境下纸牌识别:

(1)打开图片:打开图片操作有两个函数。void CCardDlg::ShowImage(IplImage* img, UINT ID)用来在MFC对话框picture控件中显示图片; void CCardDlg::OnBnClickedOpenImage()在MFC框中打开图片

void CCardDlg::ShowImage(IplImage* img, UINT ID)
{
CDC* pDC = GetDlgItem(ID)->GetDC();
HDC hDC = pDC->GetSafeHdc();
CRect rect;
GetDlgItem(ID)->GetClientRect(&rect);
SetRect(rect, rect.left, rect.top, rect.right, rect.bottom);
CvvImage cimg;
cimg.CopyOf(img);
cimg.DrawToHDC(hDC, &rect);
ReleaseDC(pDC);
}
void CCardDlg::OnBnClickedOpenImage()//打开图片
{
// TODO: 在此添加控件通知处理程序代码
CFileDialog dlg(true, _T("*.bmp"), NULL, OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
_T("image file(*.bmp;*.jpg)|*.bmp;*.jpg|All Files(*.*)|*.*|"), NULL);//弹出选择图片对话框
dlg.m_ofn.lpstrTitle = _T("open Image");
if (dlg.DoModal() != IDOK)
return;
m_strPicPath = dlg.GetPathName();
m_strPicPath.Replace(_T("//"), _T(""));
TheImage = cvLoadImage((CT2CA)m_strPicPath, 1);
if (TheImage != NULL)
{
ShowImage(TheImage, IDC_STATIC);
}
}

打开图片效果:


 
(2)二值化:调用了opencv中的cvThreshold()函数。这个函数实现的算法原理是当像素大于设定阈值时,将其设为0或255。
void CCardDlg::OnBnClickedBinary()//二值化
{
// TODO: 在此添加控件通知处理程序代码
if (TheImage != NULL)//TheImage全局变量
{
TheImage = cvLoadImage((CT2CA)m_strPicPath, 0);
cvThreshold(TheImage, TheImage, 100, 255, CV_THRESH_BINARY_INV);
ShowImage(TheImage, IDC_STATIC0);
}
}

二值化效果


 
(3)图像分割:分割函数OnBnClickedCutImage()
void CCardDlg::OnBnClickedCutImage()//图像分割
{
// TODO: 在此添加控件通知处理程序代码
IplImage* cutImage=TheImage;
if (TheImage != NULL)
{
//cvThreshold(TheImage, TheImage, 100, 255, CV_THRESH_BINARY_INV);
int width= TheImage->width / 5;
int height = TheImage->height / 3;//取到纸牌左上角的位置,给新的图片元素
cutImage->width = width;
cutImage->height = height;
int i, j;
uchar *data1 = ((uchar*)TheImage->imageData);
uchar *data2 = ((uchar*)cutImage->imageData);
int step1 = TheImage->widthStep / (sizeof(uchar));
int step2 = cutImage->widthStep / (sizeof(uchar));
for (i = 0; i < cutImage->height; i++)//像素复制到新的图片元素cutImage上
{
for (j = 0; j < cutImage->width; j++)
{
int temp=0;
temp= data1[i*step1 + j];
data2[i*step2 + j] = temp;
}
}
ShowImage(TheImage, IDC_STATIC0);
}
}
}

分割效果


 

(4)模板匹配进行识别:两个函数,图片比较函数Compare(),和识别函数void CCardDlg::OnBnClickedImageRecognize()。加载模板代码,将模板存入数组

//读入多张模板

    templeNum[0] = cvLoadImage("方块3模板.jpg", 0);//读入模板

    templeNum[1] = cvLoadImage("黑桃3模板.jpg", 0);//读入模板

    templeNum[2] = cvLoadImage("红桃5模板.jpg", 0);//读入模板

    templeNum[3] = cvLoadImage("梅花7模板.jpg", 0);//读入模板

    templeNum[4] = cvLoadImage("红桃9模板.jpg", 0);//读入模板

    templeNum[5] = cvLoadImage("方块A模板.jpg", 0);//读入模板

加载完模板后进行识别

    for (i = 0; i <= 5; i++)

    {

       cvThreshold(templeNum[i], templeNum[i],150, 255, CV_THRESH_BINARY);

       //imshow("模板",temple);

       flag = Compare(*src, *templeNum[i]);//相当于flag==similarity

       if (flag>0.96)//相似度>0.96

       {

           int k;

           k = i;//将第几个位置记录下来

           CString str;

           str.Format(_T("%lf"),flag);

           switch (k) {

           case 0:AfxMessageBox(_T("***方块3***")); AfxMessageBox(str);break;

           case 1:AfxMessageBox(_T("***黑桃3***")); AfxMessageBox(str);break;

           case 2:AfxMessageBox(_T("***红桃5***")); AfxMessageBox(str);break;

           case 3:AfxMessageBox(_T("***梅花7***")); AfxMessageBox(str);break;

           case 4:AfxMessageBox(_T("***红桃9***")); AfxMessageBox(str);break;

           case 5:AfxMessageBox(_T("***方块A***")); AfxMessageBox(str);break;

           default:AfxMessageBox(_T("匹配失败!"));

           }

       }

进行识别时编写了一个Compare()函数,对进行匹配的两张图片进行像素比较,当匹配相似度达到设定值时即匹配成功。
double CCardDlg::Compare(IplImage& src, IplImage& sample)//两张图片像素比较
{
double same = 0.0, diff = 0.0, similarity;
int i, j;
int row = sample.height;
int col = sample.width;
uchar *data1 = ((uchar*)src.imageData);
uchar *data2 = ((uchar*)sample.imageData);
int step1 = src.widthStep / (sizeof(uchar));
int step2 = sample.widthStep / (sizeof(uchar));
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
int a = data1[i*step1+j];
int b = data2[i*step2+j];
if (a==b)
{
same++;//计算像素相同的个数
}
else
diff++;//计算像素不同的个数
}
}
similarity = same / (same + diff);//计算匹配相似度
return similarity;
}

识别效果


总结:刚刚做完图像处理课程设计不久,对图像处理的理解也是不够的。此篇文章仅仅为自己的一篇记录而已。代码还有很多不足的地方,若有阅读者请多多指教。另外,由于从网上找来的图片比较正,所以就没有去处理纸牌角度校正了,这是一个不足的地方

 
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页