击中击不中属于图像形态学操作范畴,通过定义一定形状的结构元素,然后在图像中寻找与该结构元素相同的区域,找到即为击中,找不到即为击不中。
代码如下
#include<iostream>
#include<opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
//加载图像
Mat src = imread("1.png");
if (src.empty())
{
cout << "no image!" << endl;
return -1;
}
imshow("src", src);
//灰度处理
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
imshow("gray", gray);
//高斯滤波
Mat gauss;
GaussianBlur(gray, gauss, Size(5, 5), 0, 0);
imshow("gauss", gauss);
//二值化
Mat binary;
threshold(gauss, binary, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
imshow("binary", binary);
//击中操作
Mat hitImg;
Mat kern = getStructuringElement(MORPH_CROSS, Size(11, 11));
morphologyEx(binary, hitImg, MORPH_HITMISS, kern);
imshow("hitMiss", hitImg);
//膨胀一下
Mat openImg;
Mat kern2 = getStructuringElement(MORPH_RECT, Size(3, 3));
morphologyEx(hitImg, openImg, MORPH_OPEN, kern2,Point(-1,-1),2);
imshow("dilate", openImg);
//寻找轮廓
vector<vector<Point>>contours;
vector<Vec4i>hie;
Mat mask = Mat::zeros(src.size(), CV_8UC3);
findContours(openImg, contours, hie, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());
for (size_t i = 0; i < contours.size(); i++)
{
double area = contourArea(contours[i]);
if (area < 20.0)continue;
Rect rect = boundingRect(contours[i]);
drawContours(mask, contours, static_cast<int>(i), Scalar(255, 255, 255), -1, 8);
rectangle(src, rect, Scalar(0, 0, 255), 1, 8);
cout << "面积:" << area << endl;
}
imshow("mask", mask);
imshow("srcImg", src);
Mat result;
bitwise_and(src, mask, result);
imshow("result", result);
waitKey(0);
return 0;
}
原图
结果
关于图像形态学操作,选择合适的操作方法很重要,但是定义一个合适的结构元素也很关键。
而常用的一些结构元素有3*3,5*5,7*7,或者一些矩形的结构元素,image.cols*1,1*image.rows等等。