OpenCV的應用:九宮格小人識別

1、實驗內容:自動是被下列九宮格圖像中小人的位置,並將小人分割出來

2、思路分析:

本實驗的難點首先在於如何在一幅圖像中把九幅圖片分離出來,其次如何能夠從分離出來的九幅圖片中識別出小人圖像。本人的具體思路是這樣的:

  1. 分離九幅圖片:通過findContours()函數尋找到圖像中所有物體的輪廓,並用boundingRect()獲得所有輪廓的包圍矩形,但是我們需要的只是九宮格中的九個矩形區域,因此可以通過比較包圍矩形的長或者寬剔除其他干擾矩形,就會得到九個矩形區域。接着可以憑藉着九個矩形獲得灰度圖像的九個感興趣區域,並將九個感興趣區域全部輸出。
  2. 自動識別出小人圖像:可以發現,九幅圖片中,每幅圖像的黑色像素點數都不盡相同,其中小人圖像的黑色像素最少,這就是如何自動識別小人圖像的突破點。可以尋找到九幅圖像中黑色像素點最小的哪一幅,藉此間接的自動識別小人圖像。

3、本題中用到的關鍵API:

  1. cvtColor():將圖片轉換成灰度圖像
  2. threshold:將灰度圖像二值化
  3. findContours:尋找圖像的輪廓
  4. boundingRect:獲取輸入點集的包圍矩形
  5. 獲取像素的三種方式可以查看原創博客https://blog.csdn.net/qq_38316300/article/details/100109246

4、詳細代碼:

/*
*	實驗要求:自動識別圖像中小人的位置
*/

#include <opencv2/opencv.hpp>
#include <vector>
#include <iostream>

using namespace std;
using namespace cv;

//找出黑色像素最小的那個圖片
int findMinVectorNum(vector<int> temp);
int main(int argc, char ** argv) {
	Mat srcImage;
	srcImage = imread("1.png");
	if (srcImage.empty()) {
		printf("could not load this picture!\n");
		return -1;
	}
	imshow("源圖像", srcImage);
	//將圖像轉化成灰度圖像
	Mat grayImage;
	cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
	// 利用canny進行邊緣檢測
	Mat binaryImage;
	//Canny(gra yImage, binaryImage, 100, 255);
	threshold(grayImage, binaryImage, 200, 255, THRESH_BINARY);
	imshow("灰度圖像", binaryImage);
	// findcontours()獲取輪廓
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	vector<Rect> rect;
	findContours(binaryImage, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
	// boundingRect()函數獲取外圍輪廓的矩形

	for (int i = 0; i < contours.size(); i++) {
		// 根據矩形的寬來獲取源圖像中的九個方格矩形區域
		Rect tempRect = boundingRect(contours[i]);
		if (tempRect.width > 90) {
			rect.push_back(tempRect);
		}
	}
	// 繪製矩形
	Mat dstImage;
	srcImage.copyTo(dstImage);
	imshow("尋找到的矩形", dstImage);
	// //獲取圖形的感興趣區域
	imshow("圖像1", srcImage(rect[0]));
	imshow("圖像2", srcImage(rect[1]));
	imshow("圖像3", srcImage(rect[2]));
	imshow("圖像4", srcImage(rect[3]));
	imshow("圖像5", srcImage(rect[4]));
	imshow("圖像6", srcImage(rect[5]));
	imshow("圖像7", srcImage(rect[6]));
	imshow("圖像8", srcImage(rect[7]));
	imshow("圖像9", srcImage(rect[8]));
	//尋找黑色像素最少的圖片
	int width = binaryImage(rect[0]).cols;
	int height = binaryImage(rect[0]).rows;
	cout << "width" << width << endl;
	cout << "height" << height << endl;
	vector<int> blackPixNum;
	int black = 0;
	for (size_t i = 0; i < rect.size(); i++) {
		for (size_t row = 0; row < height - 6; row++) {
			for (size_t col = 0; col < width - 10; col++) {
				if (binaryImage(rect[i]).at<uchar>(row, col) == 0) {
					black += 1;
				}
			}
		}
		blackPixNum.push_back(black);
		black = 0;
	}
	cout << "blackPixNum:" << blackPixNum.size()<< endl;
	for (size_t i = 0; i < blackPixNum.size(); i++) {
		cout << "第" << i + 1<< "個圖片的黑色像素的個數" << blackPixNum[i] << endl;
	}
	// 找出九個圖像中像素最小的那一個圖片
	int minVectorNum =  findMinVectorNum(blackPixNum);
	for (size_t i = 0; i < blackPixNum.size(); i++) {
		if (blackPixNum[i] == minVectorNum) {
			imshow("最終找到的圖片", srcImage(rect[i]));
		}
	}

	//// 獲取感興趣的區域
	waitKey(0);
	return 0;
}
int findMinVectorNum(vector<int> temp) {
	int mindata = temp[0];
	int len = temp.size(), i;
	for (i = 1;i<len;i++)
	{
		if (temp[i]<mindata)
			mindata = temp[i];
	}
	return mindata;

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章