1、實驗內容:自動是被下列九宮格圖像中小人的位置,並將小人分割出來
2、思路分析:
本實驗的難點首先在於如何在一幅圖像中把九幅圖片分離出來,其次如何能夠從分離出來的九幅圖片中識別出小人圖像。本人的具體思路是這樣的:
- 分離九幅圖片:通過findContours()函數尋找到圖像中所有物體的輪廓,並用boundingRect()獲得所有輪廓的包圍矩形,但是我們需要的只是九宮格中的九個矩形區域,因此可以通過比較包圍矩形的長或者寬剔除其他干擾矩形,就會得到九個矩形區域。接着可以憑藉着九個矩形獲得灰度圖像的九個感興趣區域,並將九個感興趣區域全部輸出。
- 自動識別出小人圖像:可以發現,九幅圖片中,每幅圖像的黑色像素點數都不盡相同,其中小人圖像的黑色像素最少,這就是如何自動識別小人圖像的突破點。可以尋找到九幅圖像中黑色像素點最小的哪一幅,藉此間接的自動識別小人圖像。
3、本題中用到的關鍵API:
- cvtColor():將圖片轉換成灰度圖像
- threshold:將灰度圖像二值化
- findContours:尋找圖像的輪廓
- boundingRect:獲取輸入點集的包圍矩形
- 獲取像素的三種方式可以查看原創博客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;
}