1. 程式人生 > >【影象處理】C++實現模板匹配

【影象處理】C++實現模板匹配

//////////////////////////////////////////////////////////////////////////
	//預先判斷——3*3十字中心——區域是否相似,如果相似,則再匹配判斷。這樣可以減少判斷次數。
	//前提:模板大於9*9
	BOOL Judgement(BYTE *pTempDataBuf, BYTE *pTemplateBuf, int nTemplateHeight, int nTemplateWidth); //預先判斷

/*
//模板匹配:
//複製影象上的一塊模板大小的區域,與模板進行匹配,返回目標物的型別的資料;(點,則返回ShapePoint)
//引數:BYTE *pTempDataBuf —— 從影象上覆制模板大小的塊
		BYTE *pTemplateBuf —— 模板資料
		int nTempHeight    —— 模板高
		int nTempWidth     —— 模板寬

		int LeftDev —— 模板中邊界與目標點的左偏量
		int RightDev—— 模板中邊界與目標點的右偏量
*/
	//用來判斷是否匹配成功
	BOOL TemplateMatch_SSD(BYTE *pTempDataBuf, BYTE *pTemplateBuf, int nTemplateHeight, int nTemplateWidth);//畫素差平方和匹配
	BOOL TemplateMatch_CC(BYTE *pTempDataBuf, BYTE *pTemplateBuf, int nTemplateHeight, int nTemplateWidth);//互相關匹配
	BOOL TemplateMatch_NCC(BYTE *pTempDataBuf, BYTE *pTemplateBuf, int nTemplateHeight, int nTemplateWidth);//歸一化互相關匹配

//畫素差平方和匹配
BOOL CTemplateMatching::TemplateMatch_SSD(BYTE *pTempDataBuf, BYTE *pTemplateBuf, int nTemplateHeight, int nTemplateWidth)
{
	int m,n;
	double dSSD = 0;//差平方和
	
    unsigned char tempDatapixel;//畫素值
    unsigned char templatepixel;
	
	for (m=0; m<nTemplateHeight; m++)
    {
        for(n=0; n<nTemplateWidth; n++)
        {
			tempDatapixel = pTempDataBuf[TPos(m,n)];//模板塊畫素
            templatepixel = pTemplateBuf[TPos(m,n)];//模板畫素
            dSSD += (double)(tempDatapixel - templatepixel)*(tempDatapixel - templatepixel); //模板塊與模板裡,所有畫素值的平方和
        }
    }
	
	if (dSSD < 100)   //SSD測度的臨界值
		return 1;
	else
		return 0;
}
	
//互相關匹配
BOOL CTemplateMatching::TemplateMatch_CC(BYTE *pTempDataBuf, BYTE *pTemplateBuf, int nTemplateHeight, int nTemplateWidth)
{
	int m,n;
	double dSigmaST = 0;//中間結果——pTempDataBuf與pTemplateBuf乘積和
    double dSigmaS = 0; //中間結果——pTempDataBuf平方和
    double dSigmaT = 0; //中間結果——pTemplateBuf平方和
	double R = 0;//相似性測度

    unsigned char tempDatapixel;//畫素值
    unsigned char templatepixel;

	for (m=0; m<nTemplateHeight; m++)
    {
        for(n=0; n<nTemplateWidth; n++)
        {
			tempDatapixel = pTempDataBuf[TPos(m,n)];//模板塊畫素
            templatepixel = pTemplateBuf[TPos(m,n)];//模板畫素
			dSigmaS += (double)tempDatapixel*tempDatapixel; //模板塊裡,所有畫素值的平方和
            dSigmaT += (double)templatepixel*templatepixel; //模板裡,所有畫素值的平方和
            dSigmaST += (double)tempDatapixel*templatepixel; //模板塊與模板裡,所有畫素值的平方和
        }
    }

	R = dSigmaST/(sqrt(dSigmaT)*sqrt(dSigmaS));//相似性測度公式
	if (R > 0.85)   //相似性測度的臨界值
		return 1;
	else
		return 0;
}

//歸一化互相關匹配
BOOL CTemplateMatching::TemplateMatch_NCC(BYTE *pTempDataBuf, BYTE *pTemplateBuf, int nTemplateHeight, int nTemplateWidth)
{
	int m,n;
	double dSumST = 0;//中間結果——(Sxy - S')*(Txy - T')之和
    double dSumS = 0; //中間結果——(Sxy - S')平方和
    double dSumT = 0; //中間結果——(Txy - T')平方和

	double dSPixelSum = 0;
	double dTPixelSum = 0;

	double dNCC = 0;//歸一化相似測度
	
    unsigned char tempDatapixel;//畫素值
    unsigned char templatepixel;

	unsigned char AveraryDatapixel; //pTempDataBuf平均值
	unsigned char AveraryTemplatepixel;//pTemplateBuf平均值

	for (m=0; m<nTemplateHeight; m++)
    {
        for(n=0; n<nTemplateWidth; n++)
        {
			tempDatapixel = pTempDataBuf[TPos(m,n)];//模板塊畫素
            templatepixel = pTemplateBuf[TPos(m,n)];//模板畫素
			dSPixelSum += tempDatapixel;
			dTPixelSum += templatepixel;
			
        }
    }

	AveraryDatapixel = (unsigned char)dSPixelSum/(nTemplateHeight*nTemplateWidth);
	AveraryTemplatepixel = (unsigned char)dTPixelSum/(nTemplateHeight*nTemplateWidth);

	for (m=0; m<nTemplateHeight; m++)
    {
        for(n=0; n<nTemplateWidth; n++)
        {
			tempDatapixel = pTempDataBuf[TPos(m,n)];//模板塊畫素
            templatepixel = pTemplateBuf[TPos(m,n)];//模板畫素
			dSumS  += (double)(tempDatapixel - AveraryDatapixel)*(tempDatapixel - AveraryDatapixel); 
			dSumT  += (double)(templatepixel - AveraryTemplatepixel)*(templatepixel - AveraryTemplatepixel);
			dSumST += (double)(tempDatapixel - AveraryDatapixel)*(templatepixel - AveraryTemplatepixel);
        }
    }
	
	dNCC = dSumST/(sqrt(dSumS)*sqrt(dSumT));	////歸一化相似測度公式
	if (dNCC > 0.85)   //相似性測度的臨界值
		return 1;
	else
		return 0;
}

//////////////////////////////////////////////////////////////////////////
/*
//預先判斷——3*3十字中心——區域是否相似,如果相似,則再匹配判斷。這樣可以減少判斷次數。
//前提:模板大於9*9
*/
BOOL CTemplateMatching::Judgement(BYTE *pTempDataBuf, BYTE *pTemplateBuf, int nTemplateHeight, int nTemplateWidth)
{
	int m,n;
	double dSum = 0;

	int H = 0;//寬高都分成四份,一份的高度
	int W = 0;//一份的寬度
	
	H = nTemplateHeight/4;
	W = nTemplateWidth/4;

	//第一個3*3(上)
	for (m=H-1;m<H+2;m++)
	{
		for (n=2*W-1;n<2*W+2;n++)
		{
			if (pTempDataBuf[TPos(m,n)] == pTemplateBuf[TPos(m,n)])
				dSum++;
		}
	}

	//第二個3*3(左)
	for (m=2*H-1;m<2*H+2;m++)
	{
		for (n=W-1;n<W+2;n++)
		{
			if (pTempDataBuf[TPos(m,n)] == pTemplateBuf[TPos(m,n)])
				dSum++;
		}
	}

	//第三個3*3(中)
	for (m=2*H-1;m<2*H+2;m++)
	{
		for (n=2*W-1;n<2*W+2;n++)
		{
			if (pTempDataBuf[TPos(m,n)] == pTemplateBuf[TPos(m,n)])
				dSum++;
		}
	}

	//第四個3*3(右)
	for (m=2*H-1;m<2*H+2;m++)
	{
		for (n=3*W-1;n<3*W+2;n++)
		{
			if (pTempDataBuf[TPos(m,n)] == pTemplateBuf[TPos(m,n)])
				dSum++;
		}
	}

	//第五個3*3(下)
	for (m=3*H-1;m<3*H+2;m++)
	{
		for (n=2*W-1;n<2*W+2;n++)
		{
			if (pTempDataBuf[TPos(m,n)] == pTemplateBuf[TPos(m,n)])
				dSum++;
		}
	}

	//判斷條件,達到要求,則表示預匹配準確,反之,預匹配失敗,進行下個模板匹配
	if (dSum >= (5-1)*9)   //全部個數3*3*5
		return 1;
	else
		return 0;
}