基于opencv的视频流 模板匹配 (灰度化 二值化 )

Posted 东南坼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于opencv的视频流 模板匹配 (灰度化 二值化 )相关的知识,希望对你有一定的参考价值。

#include <cv.h>
#include <highgui.h>
#include <windows.h>

 

// 获取直方图
// 1. pImageData 图像数据
// 2. nWidth 图像宽度
// 3. nHeight 图像高度
// 4. nWidthStep 图像行大小
// 5. pHistogram 直方图
BOOL GetHistogram(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep,
int *pHistogram)
{
int i = 0;
int j = 0;
unsigned char *pLine = NULL;
// 清空直方图
memset(pHistogram, 0, sizeof(int) * 256);
for (pLine = pImageData, j = 0; j < nHeight; j++, pLine += nWidthStep)
{
for (i = 0; i < nWidth; i++)
{
pHistogram[pLine[i]]++;
}
}
return TRUE;
}

// 大津法取阈值
// 1. pImageData 图像数据
// 2. nWidth 图像宽度
// 3. nHeight 图像高度
// 4. nWidthStep 图像行大小
// 函数返回阈值
int Otsu(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep)
{
int i = 0;
int j = 0;
int nTotal = 0;
int nSum = 0;
int A = 0;
int B = 0;
double u = 0;
double v = 0;
double dVariance = 0;
double dMaximum = 0;
int nThreshold = 0;
int nHistogram[256];
// 获取直方图
GetHistogram(pImageData, nWidth, nHeight, nWidthStep, nHistogram);
for (i = 0; i < 256; i++)
{
nTotal += nHistogram[i];
nSum += (nHistogram[i] * i);
}
for (j = 0; j < 256; j++)
{
A = 0;
B = 0;
for (i = 0; i < j; i++)
{
A += nHistogram[i];
B += (nHistogram[i] * i);
}
if (A > 0)
{
u = B / A;
}
else
{
u = 0;
}
if (nTotal - A > 0)
{
v = (nSum - B) / (nTotal - A);
}
else
{
v = 0;
}
dVariance = A * (nTotal - A) * (u - v) * (u - v);
if (dVariance > dMaximum)
{
dMaximum = dVariance;
nThreshold = j;
}
}
return nThreshold;
}


// 二值化
// 1. pImageData 图像数据
// 2. nWidth 图像宽度
// 3. nHeight 图像高度
// 4. nWidthStep 图像行大小
// 5. nThreshold 阈值
BOOL Threshold(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep,
unsigned int nThreshold)
{
int i = 0;
int j = 0;
unsigned char *pLine = NULL;
for (pLine = pImageData, j = 0; j < nHeight; j++, pLine += nWidthStep)
{
for (i = 0; i < nWidth; i++)
{
if (pLine[i] >= nThreshold)
{
pLine[i] = 0x00;
}
else
{
pLine[i] = 0xff;
}
}
}
return TRUE;
}


// 二值化图像取反
void Not(IplImage *edge)
{
int i;
int j;
for (i = 0;i<edge->height;i++)
for (j = 0;j<edge->width;j++)
{
if (edge->imageData[edge->height*i + j] == 0)
edge->imageData[edge->height*i + j] = 1;
else
edge->imageData[edge->height*i + j] = 0;

}

}

BOOL FindContours(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep)
{
int i = 0;
int j = 0;
unsigned char *pLine[3] = { NULL, NULL, NULL };
for (j = 1; j < nHeight - 1; j++)
{
pLine[0] = pImageData + nWidthStep * (j - 1);
pLine[1] = pImageData + nWidthStep * j;
pLine[2] = pImageData + nWidthStep * (j + 1);
for (i = 1; i < nWidth - 1; i++)
{
if (pLine[0][i - 1] == 0xFF && pLine[0][i] == 0xFF && pLine[0][i + 1] == 0xFF &&
pLine[1][i - 1] == 0xFF && pLine[1][i] == 0xFF && pLine[1][i + 1] == 0xFF &&
pLine[2][i - 1] == 0xFF && pLine[2][i] == 0xFF && pLine[2][i + 1] == 0xFF)
{
pLine[0][i - 1] = 0;
}
else
{
pLine[0][i - 1] = pLine[1][i];
}
}
}
return TRUE;
}

BOOL erzhihua(IplImage *src)
{
// 转换图像大小
// src->width *= 0.5;
// src->height *= 0.5;
// 取图像阀值
unsigned int threshold = Otsu((unsigned char *)src->imageData, src->width, src->height, src->widthStep);

// 图像二值化
if (TRUE == Threshold((unsigned char *)src->imageData, src->width, src->height, src->widthStep,
threshold))
{
//FindContours((unsigned char *)src->imageData, src->width, src->height, src->widthStep); //画出轮廓
//图像取反
cvNot(src, src);
printf("success erzhihua!\n");
cvWaitKey(0);
}
return TRUE;
}

IplImage *templat1;
IplImage *srcResult;
IplImage *result1;
int main(int argc, char* argv[])
{

IplImage *src = cvLoadImage("..//template//122.jpg", CV_LOAD_IMAGE_GRAYSCALE);
//获取摄像头 .
CvCapture* pCapture = NULL;
IplImage *pFrame = NULL;
IplImage *tempvideodata; //初始化保存彩色图 //保存视频 相同间隔时间的 一阵图像
IplImage *g_pBinaryImage = NULL;
pCapture = cvCaptureFromCAM(0);
assert(pCapture != NULL); //断言(assert)使用,检查capture是否为空指针,为假时程序退出,并打印错误消息

//绘制对话框
CvRect rect;
rect.x = 203;
rect.y = 154;
rect.height = 36;
rect.width = 33;
//将模板二值化
erzhihua(src);
cvNamedWindow("dsc", 0);
cvShowImage("dsc", src);
//创建视频窗口
cvNamedWindow("video", 1);
pFrame = cvQueryFrame(pCapture);
cvNamedWindow("tempvideodata", 1);
//显示视屏
while (pFrame)
{
//显示 视频
pFrame = cvQueryFrame(pCapture);
if (!pFrame)
break;
cvShowImage("video", pFrame);
//转换成灰度图
tempvideodata = cvCreateImage(cvGetSize(pFrame), pFrame->depth, 1);
cvCvtColor(pFrame, tempvideodata, CV_BGR2GRAY);
// 创建二值图
g_pBinaryImage = cvCreateImage(cvGetSize(tempvideodata), IPL_DEPTH_8U, 1);
//二值化
unsigned int threshold1 = Otsu((unsigned char *)tempvideodata->imageData, tempvideodata->width, tempvideodata->height, tempvideodata->widthStep);
cvThreshold(tempvideodata, g_pBinaryImage, threshold1, 255, CV_THRESH_BINARY);
//图像取反
cvNot(g_pBinaryImage, g_pBinaryImage);
//cvSaveImage("saveImage.jpg", g_pBinaryImage);
cvShowImage("tempvideodata", g_pBinaryImage);
char c = cvWaitKey(33);
if (c == 27)
break;
//模板匹配部分
int srcW, srcH, templatW, templatH, resultH, resultW;
srcW = g_pBinaryImage->width;
srcH = g_pBinaryImage->height;
templatW = src->width;
templatH = src->height;

resultW = srcW - templatW + 1;
resultH = srcH - templatH + 1;

result1 = cvCreateImage(cvSize(resultW, resultH), IPL_DEPTH_32F, 1);

srcResult = cvCreateImage(cvGetSize(g_pBinaryImage), IPL_DEPTH_32F, 1); //1通道
templat1 = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1); //1通道

cvConvertScale(g_pBinaryImage, srcResult, 1.0 / 255, 0);
cvConvertScale(src, templat1, 1.0 / 255, 0);
cvMatchTemplate(srcResult, templat1, result1, CV_TM_SQDIFF); //模板匹配
//CV_TM_SQDIFF =0, //平方差匹配法
//CV_TM_SQDIFF_NORMED = 1, //
//CV_TM_CCORR = 2, //相关匹配法
//CV_TM_CCORR_NORMED = 3, //
//CV_TM_CCOEFF = 4, //相关匹配法
//CV_TM_CCOEFF_NORMED = 5 //

double minValue, maxValue;
CvPoint minLoc, maxLoc;
CvPoint pt1;
CvPoint pt2;
cvMinMaxLoc(result1, &minValue, &maxValue, &minLoc, &maxLoc);
printf("x_location=%d;y_location=%d\n", minLoc.x, minLoc.y); //坐标值
cvRectangle(g_pBinaryImage, minLoc, cvPoint(minLoc.x + templatW, minLoc.y + templatH), cvScalar(0, 0, 255)); //圈出开关部分
//for (int cx = 0; cx<resultW;cx++)
//{
// for (int cy = 0; cy < resultH;cy++)
// {
// float fTemp = CV_IMAGE_ELEM(result1, float, cy, cx);

// if (fTemp > 1000)
// {
// pt1 = cvPoint(cx, cy); //记录位置
// pt2 = cvPoint(pt1.x + templatW, pt1.y + templatH); //对角位置
// cvRectangle(g_pBinaryImage, minLoc, cvPoint(minLoc.x + templatW, minLoc.y + templatH), cvScalar(0, 0, 255)); //圈出开关部分
// printf("%f\n", fTemp);
// printf("x_location=%d;y_location=%d\n", minLoc.x, minLoc.y); //坐标值
// //if (minLoc.x == 432&& minLoc.y == 159)
// // printf("zuobiao 432,159 \n");
// break;
// }
// }
//}
cvShowImage("srcResult", g_pBinaryImage);

cvReleaseImage(&tempvideodata);
cvReleaseImage(&g_pBinaryImage);
cvReleaseImage(&templat1);
cvReleaseImage(&srcResult);
cvReleaseImage(&result1);
}
cvWaitKey(0);
cvDestroyAllWindows();
cvReleaseCapture(&pCapture);
cvReleaseImage(&src);
cvReleaseImage(&pFrame);
cvReleaseImage(&tempvideodata);
cvReleaseImage(&g_pBinaryImage);
cvReleaseImage(&templat1);
cvReleaseImage(&srcResult);
cvReleaseImage(&result1);
printf("Hello World!/n");
return 0;
}

以上是关于基于opencv的视频流 模板匹配 (灰度化 二值化 )的主要内容,如果未能解决你的问题,请参考以下文章

iphone opencv - 模板匹配

图像识别基于形态学和模板匹配实现扑克牌识别matlab源码

Python图像处理丨基于OpenCV和像素处理的图像灰度化处理

python opencv身份证灰度图二值化应该怎么处理

opencv之SURF图像匹配

怎样用opencv语句求二值化图像总的灰度值