微信跳一跳:基於Opencv 識別起始點及目標點位置

學習了一段時間opencv視覺編程,也不知道自己學了點啥,做一個小的東西練練手,作爲入門學習的練習吧。如果要跳起來可以用調用ADB工具進行與手機通訊實現模擬人的點擊。
  
ADB工具下載地址:https://download.csdn.net/download/llikestudy_/10826334

一、起始點識別:
在這裏插入圖片描述
  從圖可以看到,棋子是圖中不變得元素,我們可以通過模板匹配來確定妻子的位置然後通過棋子的位置,對座標進一步加工,得到起始點位置。

在這裏插入圖片描述

	//使用模板匹配匹配到圖中棋子位置
	Mat src, playsrc,local_player;
	src = imread("1.jpg");  //帶匹配圖
	playsrc = imread("2.png"); //模板(棋子)
	src.copyTo(local_player);
	int resultImage_cols = local_player.cols - playsrc.cols + 1;
	int resultImage_rows = local_player.rows - playsrc.rows + 1;
	Mat resultImage;
	resultImage.create(resultImage_cols,resultImage_rows,CV_32FC1);
	matchTemplate(local_player, playsrc, resultImage, TM_CCOEFF_NORMED);   //模板匹配

匹配到了模板位置,用線框圈出棋子位置,標出起始點。

	Point max_Loc;     //max_Loc是最佳匹配的區域左上角點
	minMaxLoc(resultImage, 0,0,0, &max_Loc, Mat()); //minMaxLoc尋找矩陣(一維數組當作向量,用Mat定義) 中最小值和最大值的位置,這裏只需要最大值,即左上角點。
	Point sport = Point(max_Loc.x + 25, max_Loc.y + 150);
	Scalar color(0, 0, 255);
	circle(local_player, sport, 6, color, -1);
	rectangle(local_player, max_Loc,Point(max_Loc.x+50,max_Loc.y+150),Scalar(255,0,255), 2, 8);
	printf("玩家落點位置:(%d,%d)\n", max_Loc.x + 50, max_Loc.y + 150);

在這裏插入圖片描述
  可以看出,棋子位置已經被標出,起始點被標出爲紅點。下一步就是尋找目標點位置。

二、目標點位置:
  首先對圖像先進行一些處理,以便操作。
  在這裏插入圖片描述
我們看出,其實我們所需要的是上半部分的區域,且上半區域有標誌等部分干擾項也將其切除。

	Mat blur;
	GaussianBlur(src, blur, Size(5, 5), 0);
	Mat canny_image;
	Canny(blur, canny_image, 1, 10);//先預處理
	
	int height, width;
	height = canny_image.rows;
	width = canny_image.cols;
	Mat crop_img;
	Rect crop_rect;
	crop_rect = Rect(0, 300, width, int(height / 2 - 300));//左上角座標,寬,高
	crop_img = canny_image(crop_rect);//取出所需要的區域(這裏記住,我們給圖像上面去除了300像素,後面計算的縱座標得加回來)

得到的效果:
在這裏插入圖片描述
  圖中看到,棋子還留有一點干擾項,也給它去掉。因爲之前已經得出了棋子位置,遍歷棋子位置,像素值置零就好了。

	for (int i = max_Loc.x; i <= max_Loc.x + 50; i++)
		for (int j = max_Loc.y; j <= max_Loc.y+150; j++)
		{
			canny_image.at<uchar>(j, i) = 0;
	
		}

效果圖:
在這裏插入圖片描述
嗯啊,現在乾淨多了。

現在我們該計算這個目標跳臺的中心點了啊,看下圖:
  在這裏插入圖片描述
由圖很容易看出,獲得最上點的x,最右點的y。

	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(crop_img, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point()); //找到關鍵的角點
	//遍歷每一個輪廓,把多餘的輪廓去掉
	Point point1;
	Point point2;
	vector<vector<Point> >::const_iterator it = contours.begin();
	while (it != contours.end()) {
		if (it->size() < 150)
			it = contours.erase(it);
		else
			++it;
	}
	int nYMin = crop_img.rows;
	int nXMin = crop_img.cols;
	int nYMax = 0;
	int nXMax = 0;
	int nIdY = 0;
	for (int i = 0; i < contours.size(); i++)
	{
		//contours[i]代表的是第i個輪廓,contours[i].size()代表的是第i個輪廓上所有的像素點數  
		for (int j = 0; j < contours[i].size(); j++)
		{
			if (contours[i][j].y < nYMin)
			{
				nYMin = contours[i][j].y;   //找到最低的y值
				point1 = contours[i][j];    //記錄  y值最低點座標
				nIdY = i;                   //記錄哪個區域內的
			}
		}
	}
	int minY = crop_img.cols;

	for (int j = 0; j < contours[nIdY].size(); j++) //在哪個區域內繼續變量 找到x最大值
	{
		if (contours[nIdY][j].x > nXMax)
		{
			nXMax = contours[nIdY][j].x;
		}
	}
	for (int j = 0; j < contours[nIdY].size(); j++)
	{//找到x中最大值上的最小值
		if (contours[nIdY][j].x == nXMax && contours[nIdY][j].y < minY)
		{
			point2 = contours[nIdY][j];
			minY = contours[nIdY][j].y;     //記錄X點的最大值
		}
	}
	point2.y = point2.y + 300; // y測得不準,因爲之前上面切掉了300像素,得加上
	Point center =  Point(point1.x, point2.y);       //返回中點座標
	printf("中心的:(%d,%d)\n", point1.x, point2.y);
	circle(local_player, center, 6, Scalar(0, 0, 255), -1);

效果如下:
在這裏插入圖片描述

兩點座標已知,求起始點和目標點距離,勾股定理。

	int A = max_Loc.x + 25 - point1.x;
	int B = max_Loc.y + 150 - point2.y;
	C = int(pow(pow(A, 2) + pow(B, 2), 0.5));

	line(local_player, sport, center, Scalar(255, 0, 255), 2, 8);

	printf("距離爲:%d", C);

在這裏插入圖片描述

好吧,最主要的兩點就得到了,剩下的自己慢慢完善就好了。如果要跳起來可以用調用ADB工具進行與手機通訊實現模擬人的點擊。

ADB工具下載地址:https://download.csdn.net/download/llikestudy_/10826334

發佈了2 篇原創文章 · 獲贊 2 · 訪問量 1064
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章