今天看论文接触到一个新词—显著性检测,刚开始没想到是一个专业词汇,查了博客发现是一种极好的目标检测算法,可用于目标检测和定位,目标ROI区域粗分割,继而进行目标图像处理。
贴出原博客链接:OpenCV-python图像显著性检测算法
据说几种算法中FT算法比较好,所以只跑了C++版的代码。
**
解释:
**图像在频率域可以分成低频部分和高频部分。低频部分反映了图像的整体信息,如物体的轮廓,基本的组成区域。高频部分反映了图像的细节信息,如物体的纹理。显著性区域检测用到的更多的是低频部分的信息。在实际进行计算时,FT方法使用窗口5*5的高斯平滑来实现对最高频的舍去。
步骤:
1、对图像进行 5*5 的高斯平滑。
2、转换颜色空间。RGB颜色空间转换为CIELAB颜色空间。
3、计算整幅图片的 l、a、b的平均值。
4、按照算法中的公式,计算每个像素l、a、b值同图像三个l、a、b均值的欧氏距离。得到显著图
5、归一化。图像中每个像素的显著值除以最大的那个显著值。得到最终的显著图。
代码:
/*===========================================================================
Copyright@hitzym, Harbin Institute of Technology
Date:Apr,13,2018
Contact:zhenyumei1995@163.com
blog: https://blog.csdn.net/yinhuan1649
===========================================================================*/
#include <iostream>
#include <opencv2/opencv.hpp>
#include <fstream>
using namespace cv;
using namespace std;
void writeMatToFile(cv::Mat& m, const char* filename) //把矩阵写入txt文件
{
std::ofstream fout(filename);
if (!fout)
{
std::cout << "File Not Opened" << std::endl;
return;
}
for (int i = 0; i<m.rows; i++)
{
for (int j = 0; j<m.cols; j++)
{
fout << m.at<double>(i, j) << "\t";
}
fout << std::endl;
}
fout.close();
}
int main() {
Mat srcimg, grgbimg, labimg;
srcimg = imread("D:/images/tool_3.jpg");
int height = srcimg.rows;
int width = srcimg.cols;
GaussianBlur(srcimg, srcimg, Size(3, 3), 0, 0, BORDER_REFLECT); // 高斯模糊
cvtColor(srcimg, labimg, COLOR_BGR2Lab); //转到lab空间
cv:Scalar tempVal = cv::mean(labimg); //求各通道均值
double lmean = tempVal.val[0];
double amean = tempVal.val[1];
double bmean = tempVal.val[2];
Mat salientMap = Mat::zeros(height, width, CV_64F); //定义显著图,因为是double类型,所以在这里初始化类型为CV_64F
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
//显著值计算,对应matlab代码中sm = (l-lm).^2 + (a-am).^2 + (b-bm).^2;
salientMap.at<double>(i, j) = ((double)labimg.at<Vec3b>(i, j)[0] - lmean)*((double)labimg.at<Vec3b>(i, j)[0] - lmean)
+ ((double)labimg.at<Vec3b>(i, j)[1] - amean)*((double)labimg.at<Vec3b>(i, j)[1] - amean)
+ ((double)labimg.at<Vec3b>(i, j)[2] - bmean)*((double)labimg.at<Vec3b>(i, j)[2] - bmean);
}
}
//double max, min;
//cv::Point min_loc, max_loc;
//cv::minMaxLoc(salientMap, &min, &max, &min_loc, &max_loc);//求mat中最值
//cout << "max:"<< max << endl;
//for (int i = 0; i < salientMap.rows; i++)
//{
// for (int j = 0; j < salientMap.cols; j++)
// {
// salientMap.at<double>(i, j) = salientMap.at<double>(i, j) / max;
// }
//}
normalize(salientMap, salientMap, 1.00, 0.00, NORM_MINMAX); // 1值归一化
writeMatToFile(salientMap, "F:\\test.txt");
cout << "yes!!" << endl;
//cout << "salientMap:" << salientMap << endl;
imshow("src", srcimg);
imshow("salientMap:", salientMap);
cout << salientMap.channels() << endl;
waitKey();
system("pause");
return 0;
}