使用openCV的显着性图

时间:2017-10-31 08:19:05

标签: c++ macos opencv

我正在尝试使用此处提出的代码http://ivrlwww.epfl.ch/supplementary_material/RK_CVPR09/进行彩色图像的显着性检测。提出的代码与在windows中开发的GUI相关联。在我的情况下,我想在Mac OsX上使用OpenCv库来读取初始图像并写出显着性图结果。因此,我选择了四个主要功能,并使用OpenCV修改了读写块。我得到了以下结果,这些结果与作者所获得的结果略有不同:

Original Image

Author saliency map

Obtained saliency map

以下是四个功能。我做错了有什么不对吗?我小心地考虑在OpenCV中,颜色被描述为B-G-R而不是R-G-B。

#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

void RGB2LAB2(
const vector<vector<uint> > &ubuff,
vector<double>&                 lvec,
vector<double>&                 avec,
vector<double>&                 bvec){

int sz = int(ubuff.size());
cout<<"sz "<<sz<<endl;
lvec.resize(sz);
avec.resize(sz);
bvec.resize(sz);

for( int j = 0; j < sz; j++ ){
    int sR = ubuff[j][2]; 
    int sG = ubuff[j][1]; 
    int sB = ubuff[j][0]; 
    //------------------------
    // sRGB to XYZ conversion
    // (D65 illuminant assumption)
    //------------------------
    double R = sR/255.0;
    double G = sG/255.0;
    double B = sB/255.0;

    double r, g, b;

    if(R <= 0.04045)    r = R/12.92;
    else                r = pow((R+0.055)/1.055,2.4);
    if(G <= 0.04045)    g = G/12.92;
    else                g = pow((G+0.055)/1.055,2.4);
    if(B <= 0.04045)    b = B/12.92;
    else                b = pow((B+0.055)/1.055,2.4);

    double X = r*0.4124564 + g*0.3575761 + b*0.1804375;
    double Y = r*0.2126729 + g*0.7151522 + b*0.0721750;
    double Z = r*0.0193339 + g*0.1191920 + b*0.9503041;
    //------------------------
    // XYZ to LAB conversion
    //------------------------
    double epsilon = 0.008856;  //actual CIE standard
    double kappa   = 903.3;     //actual CIE standard

    double Xr = 0.950456;   //reference white
    double Yr = 1.0;        //reference white
    double Zr = 1.088754;   //reference white

    double xr = X/Xr;
    double yr = Y/Yr;
    double zr = Z/Zr;

    double fx, fy, fz;
    if(xr > epsilon)    fx = pow(xr, 1.0/3.0);
    else                fx = (kappa*xr + 16.0)/116.0;
    if(yr > epsilon)    fy = pow(yr, 1.0/3.0);
    else                fy = (kappa*yr + 16.0)/116.0;
    if(zr > epsilon)    fz = pow(zr, 1.0/3.0);
    else                fz = (kappa*zr + 16.0)/116.0;

    lvec[j] = 116.0*fy-16.0;
    avec[j] = 500.0*(fx-fy);
    bvec[j] = 200.0*(fy-fz);
    }
}


void GaussianSmooth(
const vector<double>&           inputImg,
const int&                      width,
const int&                      height,
const vector<double>&           kernel,
vector<double>&                 smoothImg){

int center = int(kernel.size())/2;

int sz = width*height;
smoothImg.clear();
smoothImg.resize(sz);
vector<double> tempim(sz);
int rows = height;
int cols = width;

int index(0);
 for( int r = 0; r < rows; r++ ){
    for( int c = 0; c < cols; c++ ){ 
        double kernelsum(0);
        double sum(0);
        for( int cc = (-center); cc <= center; cc++ ){
            if(((c+cc) >= 0) && ((c+cc) < cols)){
                sum += inputImg[r*cols+(c+cc)] * kernel[center+cc];
                kernelsum += kernel[center+cc];
            }
        }
        tempim[index] = sum/kernelsum;
        index++;
    }
 }
 int index = 0;
 for( int r = 0; r < rows; r++ ){
    for( int c = 0; c < cols; c++ ){
        double kernelsum(0);
        double sum(0);
        for( int rr = (-center); rr <= center; rr++ ){
            if(((r+rr) >= 0) && ((r+rr) < rows)){
               sum += tempim[(r+rr)*cols+c] * kernel[center+rr];
               kernelsum += kernel[center+rr];
            }
        }
        smoothImg[index] = sum/kernelsum;
        index++;
    }
   }
}


void GetSaliencyMap(
const vector<vector<uint> >&inputimg,
const int&                      width,
const int&                      height,
vector<double>&                 salmap,
const bool&                     normflag){

int sz = width*height;
salmap.clear();
salmap.resize(sz);

vector<double> lvec(0), avec(0), bvec(0);
RGB2LAB2(inputimg, lvec, avec, bvec);

double avgl(0), avga(0), avgb(0);
for( int i = 0; i < sz; i++ ){
    avgl += lvec[i];
    avga += avec[i];
    avgb += bvec[i];
 }

avgl /= sz;
avga /= sz;
avgb /= sz;

vector<double> slvec(0), savec(0), sbvec(0);

vector<double> kernel(0);
kernel.push_back(1.0);
kernel.push_back(2.0);
kernel.push_back(1.0);

GaussianSmooth(lvec, width, height, kernel, slvec);
GaussianSmooth(avec, width, height, kernel, savec);
GaussianSmooth(bvec, width, height, kernel, sbvec);

for( int i = 0; i < sz; i++ ){
    salmap[i] = (slvec[i]-avgl)*(slvec[i]-avgl) +
                (savec[i]-avga)*(savec[i]-avga) +
                (sbvec[i]-avgb)*(sbvec[i]-avgb);
 } 


if( true == normflag ){
    vector<double> normalized(0);
    Normalize(salmap, width, height, normalized);
    swap(salmap, normalized);
 }
}

void Normalize(
const vector<double>&           input,
const int&                      width,
const int&                      height,
vector<double>&                 output,
const int&                      normrange = 255){

double maxval(0);
double minval(DBL_MAX);
int i(0);
for( int y = 0; y < height; y++ ){
    for( int x = 0; x < width; x++ ){
        if( maxval < input[i] ) maxval = input[i];
        if( minval > input[i] ) minval = input[i];
        i++;
        }
     }
 }

 double range = maxval-minval;
 if( 0 == range ) range = 1;
 int i(0);
 output.clear();
 output.resize(width*height);
 for( int y = 0; y < height; y++ ){
    for( int x = 0; x < width; x++ ){
        output[i] = ((normrange*(input[i]-minval))/range);
        i++;
        }
    }
}

int main(){

Mat image;
image = imread( argv[1], 1 );
if ( !image.data ){

    printf("No image data \n");
    return -1;
}

std::vector<vector<uint>>array(image.cols*image.rows,vector<uint>
(3,0));  

for(int y=0;y<image.rows;y++){
  for(int x=0;x<image.cols;x++){
    Vec3b color= image.at<Vec3b>(Point(x,y));
    array[image.cols*y+x][0]=color[0]; array[image.cols*y+x]
    [1]=color[1];array[image.cols*y+x][2]=color[2];
  }
} 


vector<double> salmap; bool normflag=true;

GetSaliencyMap(array, image.size().width, image.size().height,  salmap, 
normflag);

Mat output;
output = Mat( image.rows, image.cols,CV_8UC1);
int k=0;

for(int y=0;y<image.rows;y++){
  for(int x=0;x<image.cols;x++){
    output.at<uchar>(Point(x,y)) = int(salmap[k]);
    k++;
  }
}

imwrite("test_saliency_blackAndWhite.jpg", output ); 
return 0;
}

0 个答案:

没有答案