基于形态学的红外弱小目标提取是指利用形态学的方法从红外图像中识别和提取出那些 尺寸较小、强度较弱的目标或者特征。
形态学方法通常涉及形态学操作,如腐蚀、膨胀、开运算、闭运算等,这些操作可以对图像进行局部结构的操作和特征的增强,从而有助于弱小目标的凸显,从而帮助提取出目标。
本次实验用的是垃圾算法,主要操作就是像素阈值分割,面积收缩。
1、实验步骤
- 灰度载入源图像,判断图像是否正确载入;
- 观察图像是否有噪声,若图像有噪声对图像进行去噪处理。如图像0003.bmp和0005.bmp有高斯噪声,用5×5高斯卷积核去噪处理;
- 根据待提取红外弱小目标像素值设置进行两次阈值化处理,使待提取红外弱小目标与背景图像分割;
- 用合适结构元素对3)处理后图像进行 击中击不中操作;
- 对击中目标进行形态学膨胀操作;
- 绘制膨胀后图形外轮廓;
- 计算轮廓面积,根据面积筛选待提取红外弱小目标;
- 在源图中根据筛选目标位置绘制框选矩形。
1.1、3×3高斯滤波
0003图像,用3×3高斯核滤波,用【171,190】阈值化处理,红外目标块像素值为下表,可见还有较明显高斯噪声。
162 | 169 | 180 | 174 | 170 |
161 | 173 | 186 | 184 | 175 |
172 | 185 | 190 | 193 | 173 |
172 | 181 | 185 | 189 | 173 |
159 | 166 | 165 | 167 | 163 |
1.2、5×5高斯滤波
0003图像,用5×5高斯核滤波,用【170,188】阈值化处理,红外目标块像素值为下表,相较3×3高斯卷积核已有较大改善。
164 | 170 | 175 | 174 | 167 |
167 | 175 | 183 | 182 | 171 |
171 | 180 | 187 | 185 | 173 |
170 | 176 | 181 | 180 | 171 |
162 | 165 | 167 | 167 | 163 |
2、效果展示
3、代码
提供0001和0003代码,其它类似,自己调参。
3.1、0001代码
// 0001代码
void InfraredTarget0001()
{
Mat src, dst;
String Path = "C:/Users/39686/Desktop/红外弱小目标提取样例/0001.bmp";
src = imread(Path);
namedWindow("src0001", WINDOW_NORMAL);
imshow("src0001", src);
if (src.empty())
{
cout << "could not load image..." << endl;
return;
}
Mat gray;
cvtColor(src, gray, CV_BGR2GRAY);
//二值化
Mat binary;
threshold(gray, binary, 200, 255, THRESH_BINARY_INV);
namedWindow("binary0001", WINDOW_NORMAL);
imshow("binary0001", binary);
vector<vector<Point>>contours;
vector<Vec4i>hierarchy;
Mat mask = Mat::zeros(src.size(), CV_8UC3);
//findContours输入为8位单通道图像
findContours(binary, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < (contours.size()); i++)
{
double area = contourArea(contours[i]);
if (area > 80.0)continue;
Rect rect = boundingRect(contours[i]);
//drawContours(dst, contours, i, Scalar(255), FILLED, 8, hierarchy);
rectangle(src, rect, Scalar(0, 0, 255), 1, 8);
}
namedWindow("dst0001", WINDOW_NORMAL);
imshow("dst0001", src);
return;
}
3.2、0003代码
// 0003代码
void InfraredTarget0003()//
{
Mat src, dst;
String Path = "C:/Users/39686/Desktop/红外弱小目标提取样例/0003.bmp";
src = imread(Path);
namedWindow("src0003", WINDOW_NORMAL);
imshow("src0003", src);
if (src.empty())
{
cout << "could not load image..." << endl;
return;
}
Mat gauss;
GaussianBlur(src, gauss, Size(5, 5), 0, 0);
Mat gray;
cvtColor(gauss, gray, CV_BGR2GRAY);
//二值化
Mat binary, hitImg;
threshold(gray, binary, 185, 255, 3);
threshold(binary, binary, 191, 255, 4);
namedWindow("binary0003", WINDOW_NORMAL);
imshow("binary0003", binary);
//膨胀
Mat kern2 = getStructuringElement(MORPH_RECT, Size(25,25));
morphologyEx(binary, hitImg, MORPH_CLOSE, kern2, Point(-1, -1), 1);
namedWindow("dilate", WINDOW_NORMAL);
imshow("dilate", hitImg);
float kernal_data[5][5] =
{
{-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1},
};
Mat kernel = Mat(5, 5, CV_32FC1, &kernal_data);
//击中操作
morphologyEx(binary, hitImg, MORPH_HITMISS, kernel);
bitwise_not(hitImg, hitImg);
namedWindow("hit0003", WINDOW_NORMAL);
imshow("hit0003", hitImg);
//膨胀
vector<vector<Point>>contours;
vector<Vec4i>hierarchy;
Mat mask = Mat::zeros(src.size(), CV_8UC3);
//findContours输入为8位单通道图像
findContours(hitImg, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < (contours.size()); i++)
{
double area = contourArea(contours[i]);
if (area > 20.0)continue;
//if (area < 64.5)continue;
Rect rect = boundingRect(contours[i]);
drawContours(mask, contours, i, Scalar(255), FILLED, 8, hierarchy);
rectangle(src, rect, Scalar(0, 0, 255), 1, 8);
}
namedWindow("dst0003", WINDOW_NORMAL);
imshow("dst0003", src);
return;
}
大功告成!