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;
}