FT算法来自文献:《Frequency-tuned Salient Region Detection》
作者主页:
http://ivrlwww.epfl.ch/supplementary_material/RK_CVPR09/
FT算法由Achanta等提出,利用颜色特征的中央-周边算子来得到显著图。其求解过程非常简单:
其算法原理如下图所示:
原理比较简单:
作者主要利用的是颜色特征和亮度特征。
- 对图像img进行高斯滤波得到gfrgb;
- 将图像imgrgb由RGB颜色空间转换为LAB颜色空间imglab;
- 对转换后的图像imglab 的L,A,B三个通道的图像分别取均值得到lm,am,bm;
- 计算显著值,即对分别对三个通道的均值图像和滤波得到的图像取欧氏距离并求和;
- 利用最大值对显著图归一化。
作者主页开源了其matlab代码,如下:
im=imread('./srcimgs/test.jpg'); %读图
gfrgb = imfilter(im, fspecial('gaussian', 3, 3), 'symmetric', 'conv'); %高斯滤波,核3*3或5*5
%gfrgb = im;
cform = makecform('srgb2lab');%颜色空间转换,RGB--->Lab空间,获取一个转换模板cform
lab = applycform(gfrgb,cform);%颜色空间转换,完成RGB--->Lab空间转换
l = double(lab(:,:,1));%L通道
lm = mean(mean(l));%整幅图片的l均值
a = double(lab(:,:,2));
am = mean(mean(a));%整幅图片的a均值
b = double(lab(:,:,3));
bm = mean(mean(b));%整幅图片的b均值
sm = (l-lm).^2 + (a-am).^2 + (b-bm).^2;%计算像素的显著度
s=max(sm(:)); %显著图中最大值
sa=sm./s; %归一化
imshow(sa); %显示
matlab代码运行结果:
原图:
FT显著检测结果:
尝试用opencv实现了下,代码比较简单,其中转lab空间的部分直接调用了opencv中的cvtcolor函数,不知道为什么搜其它博客很少直接这么做的,我输入了一张测试图进行测试,转出的lab空间中的lab三通道值与作者提供的matlab代码中的数值大致相同,不同应该是因为计算时浮点数不同。
实现环境:VS2013 + opencv2.4.9
代码:
/*===========================================================================
Copyright@hitzym, Harbin Institute of Technology
Date:Apr,13,2018
Contact:[email protected]
blog: https://blog.csdn.net/yinhuan1649
===========================================================================*/
#include <iostream>
#include <highgui.h>
# 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("./srcimgs/test.jpg");
int height = srcimg.rows;
int width = srcimg.cols;
GaussianBlur(srcimg, srcimg, Size(3, 3), 0, 0, BORDER_REFLECT); // 高斯模糊
cvtColor(srcimg, labimg, CV_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("salientMap:", salientMap);
waitKey();
system("pause");
return 0;
}
opencv+vs FT显著图检测结果:
matlab(上)与opencv(下)对比:
如有错误之处敬请指正!
Reference
1. http://ivrlwww.epfl.ch/supplementary_material/RK_CVPR09/
2. https://blog.csdn.net/qq_36130482/article/details/78990635