丁香五月婷婷黄色视频_97在线看观看免费_男女xo嘿咻嘿咻动态图_最近更新在线中文字幕人妻

?

基于匹配模板的術(shù)語(yǔ)自動(dòng)翻譯方法 基于openCV的形狀模版匹配

日期:2023-03-11 12:39:36 / 人氣: 769 / 發(fā)布者:成都翻譯公司

生成旋轉(zhuǎn)模版的問(wèn)題openCV沒(méi)有自帶的旋轉(zhuǎn)函數(shù),需要通過(guò)getRotationMatrix2D生成旋轉(zhuǎn)矩陣,再用warpAffine進(jìn)行仿射變換。但是warpAffine生成的圖形會(huì)自動(dòng)進(jìn)行裁剪,會(huì)帶來(lái)一些問(wèn)題,因此需要稍微修改(詳情見(jiàn)imrotate函數(shù))。openCV一些函數(shù)的源代碼在內(nèi)部還是進(jìn)行了hal庫(kù)的調(diào)用,用戶沒(méi)有辦法修改,因此沒(méi)有辦法在函數(shù)內(nèi)部進(jìn)行算法修改。

原意

果然,halcon用的順手,人變懶了。正好有個(gè)項(xiàng)目需要自己寫(xiě)一個(gè)形狀匹配的程序,就用它來(lái)實(shí)踐。程序不是很復(fù)雜,速度和halcon中的find_scaled_shape_model還是有差距的。我目前不知道。如何進(jìn)一步改進(jìn),暫且。如果大家有什么改進(jìn)的想法,大佬們可以評(píng)論,這樣你們才能繼續(xù)進(jìn)步。

想法

主要思想還是基于散點(diǎn)的重合度。雖然 openCV 自帶了 matchTemplate 和 matchShape 函數(shù),但它內(nèi)部是進(jìn)行遍歷像素矩計(jì)算的。由于檢測(cè)圖像中存在干擾邊緣,這些函數(shù)對(duì)于形狀匹配(局部像素點(diǎn)集匹配)是不適合的。當(dāng)然,這些功能還是很快的。目前,我不知道如何達(dá)到相同的速度。

算法實(shí)現(xiàn)過(guò)程中遇到幾個(gè)問(wèn)題:

1.生成旋轉(zhuǎn)模板的問(wèn)題

openCV本身沒(méi)有旋轉(zhuǎn)函數(shù),需要通過(guò)getRotationMatrix2D生成旋轉(zhuǎn)矩陣,然后使用warpAffine進(jìn)行仿射變換。但是warpAffine生成的圖形會(huì)被自動(dòng)裁剪,會(huì)造成一些問(wèn)題,所以需要稍微修改一下(詳見(jiàn)imrotate函數(shù))。

2. 遍歷邊緣點(diǎn)或進(jìn)行卷積的問(wèn)題

由于openCV和halcon兩者在取像素上都很慢,所以只能用filter2D來(lái)做比較。不得不說(shuō)openCV自帶的硬件加速庫(kù)還是很高效的。

3. 遍歷計(jì)算速度太慢

openCV的一些函數(shù)的源碼在內(nèi)部還是被hal庫(kù)調(diào)用了,用戶沒(méi)有辦法修改,所以也沒(méi)有辦法修改函數(shù)內(nèi)部的算法。嘗試使用ppl庫(kù)進(jìn)行并行加速,效果還不錯(cuò)。

程序說(shuō)明

(1) 先修改金字塔層級(jí)PyrLevel基于匹配模板的術(shù)語(yǔ)自動(dòng)翻譯方法,層級(jí)越大搜索速度越快。主函數(shù)中有放大的邊緣圖像。根據(jù)邊緣是否清晰修改PyrLevel和Canny函數(shù)的閾值保證待檢測(cè)圖像,且模板圖片邊緣清晰完整。

(2)如果找不到,適當(dāng)降低minScore,越接近0基于匹配模板的術(shù)語(yǔ)自動(dòng)翻譯方法,搜索相似度容忍度越大,但運(yùn)行速度越慢。

函數(shù)片段

具體代碼項(xiàng)目見(jiàn)

/*************************************************
Function:       //	CreateScaledShapeModel
Description:    //	創(chuàng)建模版集
Input:          //	Template:模版圖片的邊緣圖
					PyrLevel:金字塔縮小層數(shù)
					AngleStart,AngleExtent,AngleStep:旋轉(zhuǎn)角度候選參數(shù)
					ScaleMin,ScaleMax,ScaleStep:縮放比例候選參數(shù)
Output:         //	pModelImageSet,pModelPointSet,pScaleSet,pAngleSet:模版集指針
Return:         //  無(wú)
Others:         //	
*************************************************/
void CreateScaledShapeModel(Mat Template, int PyrLevel, int AngleStart, int AngleExtent, int AngleStep, float ScaleMin, float ScaleMax, float ScaleStep, 	vector* pModelImageSet, vector* pModelPointSet, vector* pScaleSet, vector* pAngleSet)
{
	vector ModelImageSet;
	vector ModelPointSet;
	vector AngleSet;
	vector ScaleSet;
	while (ScaleMin <= ScaleMax)
	{
		cout << ScaleMax << endl;
		ScaleSet.push_back(ScaleMax);
		ScaleMax -= ScaleStep;
	}
	while (AngleStart <= AngleExtent)
	{
		cout << AngleExtent << endl;
		AngleSet.push_back(AngleExtent);
		AngleExtent -= AngleStep;
	}
	//模版生成	
	for (int level = 0; level <= PyrLevel; level++)
	{
		Mat pyrmodelImage = Template;
		for (int i = 0; i < level; i++)
		{
			pyrDown(pyrmodelImage, pyrmodelImage);
		}
		//縮放
		for (int i = 0; i < ScaleSet.size(); i++)
		{
			Mat scaleImage;
			resize(pyrmodelImage, scaleImage, Size(round(pyrmodelImage.cols*ScaleSet[i]), round(pyrmodelImage.cols*ScaleSet[i])), 0, 0, INTER_LINEAR);
			//旋轉(zhuǎn)
			for (int j = 0; j < AngleSet.size(); j++)
			{
				Mat rotateImage;
				imrotate(scaleImage, rotateImage, AngleSet[j]);
				//threshold(rotateImage, rotateImage, 1, 255, 0);
				Canny(rotateImage, rotateImage, 50, 100, 3, false);
				rotateImage /= 255;
				//imshow("旋轉(zhuǎn)", rotateImage);
				//imwrite("旋轉(zhuǎn).jpg", rotateImage);
				//waitKey(0);
				ModelImageSet.push_back(rotateImage);
				int pointNum = 0;
				for (int i = 0; i < rotateImage.cols; i++)
				{
					for (int j = 0; j < rotateImage.rows; j++)
					{
						if (rotateImage.at(Point(i, j)) != 0)
							pointNum++;
					}
				}
				ModelPointSet.push_back(pointNum);
				rotateImage.release();
			}
			scaleImage.release();
		}
	}
	*pModelImageSet = ModelImageSet;
	*pModelPointSet = ModelPointSet;
	*pAngleSet = AngleSet;
	*pScaleSet = ScaleSet;
}
/*************************************************
Function:       //	FindScaledShapeModel
Description:    //	在一張圖片中搜索與模版相似的圖形
Input:          //	Image:待檢測(cè)圖片
					ModelImageSet,ModelPointSet,ScaleSet,AngleSet:模版集
					PyrLevel:金字塔縮小層數(shù)
					MinScore:篩選相似度閾值		
Output:         //	pRow,pCol,pScale,pAngle,pScore:輸出匹配到的元素參數(shù)集合的指針
Return:         //  無(wú)
Others:         //	使用該函數(shù)前需要先調(diào)用CreateScaledShapeModel
*************************************************/
void FindScaledShapeModel(Mat Image, vector ModelImageSet, vector ModelPointSet, vector ScaleSet, vector AngleSet, int PyrLevel, float MinScore,	vector* pRow, vector * pCol, vector* pScale, vector* pAngle, vector* pScore)
{
	mutex mt;
	Mat modelImage = ModelImageSet[0];
	vector Row;
	vector Col;
	vector Scale;
	vector Angle;
	vector Score;
	bool findFlag = false;
	//金字塔分層匹配
	for (int level = PyrLevel; !findFlag && level >= PyrLevel; level--)
	{		
		Mat pyrsrcImage = Image;
		for (int i = 0; i < level; i++)
		{
			pyrDown(pyrsrcImage, pyrsrcImage);
		}
		int kernSize = floor(sqrt(min(pyrsrcImage.rows / 100, pyrsrcImage.cols / 100)));		
		Mat kern = Mat::ones(2 * kernSize + 1, 2 * kernSize + 1, CV_8U);
			
		Mat blurImage;
		filter2D(pyrsrcImage, blurImage, pyrsrcImage.depth(), kern);		
		//imshow("糊化原圖", blurImage);
		//moveWindow("糊化原圖", 0, 0);
		//waitKey(10);
		Mat tempblurImage;
		blurImage.convertTo(tempblurImage, CV_8U);
		tempblurImage /= 255;
		int parallelnum = ScaleSet.size() *AngleSet.size();
		parallel_for(0, parallelnum, [&](int k)	
		{
			Mat scoreImage(tempblurImage.size(), CV_16U);
			Mat tempmodelImage = ModelImageSet.at(ModelImageSet.size()- 1 - k);
			int temppointNum = ModelPointSet.at(ModelPointSet.size() - 1 - k);
			float max_score = 0;		
			/*imshow("模版", tempmodelImage);
			resizeWindow("模版", tempmodelImage.rows, tempmodelImage.cols);		
			moveWindow("模版", blurImage.cols,0);
			waitKey(10);*/
			//double start = static_cast(getTickCount());
			filter2D(tempblurImage, scoreImage, scoreImage.depth(), tempmodelImage);
			//double time = ((double)getTickCount() - start) / getTickFrequency();
			//cout << "所用時(shí)間為:" << time << "秒" << endl;
			mt.lock();
			while (1)
			{
				double v_min, v_max;
				int idx_min[2] = { 255,255 }, idx_max[2] = { 255, 255 };
				minMaxIdx(scoreImage, &v_min, &v_max, idx_min, idx_max);
				scoreImage.at(idx_max[0], idx_max[1]) = 0;
				
				max_score = v_max / temppointNum;
				//cout << "第" << level << "層" << "第" << k + 1 << "個(gè)成績(jī):" << max_score << endl;
				if (max_score > MinScore)
				{
					float scale = ScaleSet[ScaleSet.size() - 1 - (k) / AngleSet.size()];
					float angle = AngleSet[AngleSet.size() - 1 - (k) % AngleSet.size()];
					//int selectx = (idx_max[1] - (tempmodelImage.cols - 1) / 2)*pow(2, level);
					//int selecty = (idx_max[0] - (tempmodelImage.rows - 1) / 2)*pow(2, level);
					//int pyrselectx = idx_max[1] - tempmodelImage.cols / 2;
					//int pyrselecty = idx_max[0] - tempmodelImage.rows / 2;
					Row.push_back(idx_max[1] * pow(2, level));
					Col.push_back(idx_max[0] * pow(2, level));
					Scale.push_back(scale);
					Angle.push_back(angle);
					Score.push_back(max_score);
					//cout << Point(selectx, selecty) << " " << Point(pyrselectx, pyrselecty) << endl;
					//rectangle(blurImage, Rect(pyrselectx, pyrselecty, tempmodelImage.cols, tempmodelImage.rows), 255, 2, 8);
					//rectangle(Image, Rect(selectx, selecty, modelImage.cols / scale, modelImage.rows / scale), 255, 2, 8);
					//imshow("縮放圖位置", blurImage);
					//imshow("原圖位置", Image);
					//waitKey(0);
					//findFlag = true;				
				}		
				else break;
			}
			tempmodelImage.release();
			scoreImage.release();
			mt.unlock();
		}
		);
		for (int m = 0; m < Row.size() ; m++)
		{
			for (int n = m+1; n < Row.size() ; n++)
			{
				if (abs(Row[n] - Row[m])= Score[m])
					{
						swap(Row[m], Row[n]);
						swap(Col[m], Col[n]);
						swap(Scale[m], Scale[n]); 
						swap(Angle[m], Angle[n]); 
						swap(Score[m], Score[n]);
						Row.erase(Row.begin() + n);
						Col.erase(Col.begin() + n);
						Scale.erase(Scale.begin() + n);
						Angle.erase(Angle.begin() + n);
						Score.erase(Score.begin() + n);
						n = m ;
					}
				
				}
			}
		}
		*pRow = Row;
		*pCol = Col;
		*pScale = Scale;
		*pAngle = Angle;
		*pScore = Score;
	}
}
void imrotate(Mat& img, Mat& newIm, double angle) 
{
	int heightNew = int(img.cols*fabs(sin(angle*3.14 / 180)) + img.rows * fabs(cos(angle*3.14 / 180)));
	int widthNew = int(img.rows*fabs(sin(angle*3.14 / 180)) + img.cols * fabs(cos(angle*3.14 / 180)));
	int len = max(img.cols, img.rows);
	Point2f pt(len / 2., len / 2.);
	Mat r = getRotationMatrix2D(pt, angle, 1.0);
	r.at(0, 2) += (widthNew - img.cols) / 2;
	r.at(1, 2) += (heightNew - img.rows) / 2;	
	warpAffine(img, newIm, r, Size(widthNew, heightNew), INTER_LINEAR, BORDER_REPLICATE);
}

相關(guān)閱讀Relate

  • 法國(guó)簽證營(yíng)業(yè)執(zhí)照翻譯件模板 你與申根簽證只有一條推送的距離
  • 江蘇省增值稅發(fā)票翻譯模板 江蘇稅務(wù)局出口貨物退(免)稅申報(bào)管理系統(tǒng)軟件
  • 肄業(yè)證書(shū)翻譯模板 復(fù)旦大學(xué)學(xué)生學(xué)業(yè)證明文書(shū)管理細(xì)則(試行)
  • 四級(jí)英語(yǔ)作文模板帶翻譯 大學(xué)英語(yǔ)四級(jí)翻譯模擬訓(xùn)練及答案
  • 社會(huì)某信用代碼證翻譯模板 js驗(yàn)證某社會(huì)信用代碼,某社會(huì)信用代碼 驗(yàn)證js,js+驗(yàn)證+社會(huì)信用代碼證
  • 美國(guó)移民證件翻譯模板 日語(yǔ)簽證翻譯聊聊身份證翻譯模板
  • 翻譯軟件模板 人類(lèi)史上*實(shí)用的的文檔快速翻譯指南
  • 江蘇省增值稅發(fā)票翻譯模板 江蘇出口貨物退(免)稅申報(bào)管理服務(wù)平臺(tái)
  • 瑞士簽證房產(chǎn)證翻譯件模板 瑞士探親簽證—就讀子女
  • 日語(yǔ)戶口本翻譯模板 戶口本翻譯價(jià)格_戶口本翻譯一般多少錢(qián)?
  • 基于匹配模板的術(shù)語(yǔ)自動(dòng)翻譯方法 基于openCV的形狀模版匹配 www.angeldealglobal.com/fymb/8524.html
    ?
    本站部分內(nèi)容和圖片來(lái)源于網(wǎng)絡(luò)用戶和讀者投稿,不確定投稿用戶享有完全著作權(quán),根據(jù)《信息網(wǎng)絡(luò)傳播權(quán)保護(hù)條例》,如果侵犯了您的權(quán)利,請(qǐng)聯(lián)系:chinazxzy@163.com,及時(shí)刪除。
    Go To Top 回頂部
    • 掃一掃,微信在線