from:http://blog.csdn.net/onezeros/article/details/6299745
先看几张效果图吧
效果图:
可以直接测试的代码:
头文件:
- // Saliency.h: interface for the Saliency class.
- //
- //
- //===========================================================================
- // Copyright (c) 2009 Radhakrishna Achanta [EPFL]
- //===========================================================================
- #if !defined(_SALIENCY_H_INCLUDED_)
- #define _SALIENCY_H_INCLUDED_
- #include <vector>
- #include <cfloat>
- using namespace std;
- class Saliency
- {
- public:
- Saliency();
- virtual ~Saliency();
- public:
- void GetSaliencyMap(
- const vector<unsigned int>& inputimg,//INPUT: ARGB buffer in row-major order
- const int& width,
- const int& height,
- vector<double>& salmap,//OUTPUT: Floating point buffer in row-major order
- const bool& normalizeflag = true);//false if normalization is not needed
- private:
- void RGB2LAB(
- const vector<unsigned int>& ubuff,
- vector<double>& lvec,
- vector<double>& avec,
- vector<double>& bvec);
- void GaussianSmooth(
- const vector<double>& inputImg,
- const int& width,
- const int& height,
- const vector<double>& kernel,
- vector<double>& smoothImg);
- //==============================================================================
- /// Normalize
- //==============================================================================
- 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++;
- }
- }
- }
- };
- #endif // !defined(_SALIENCY_H_INCLUDED_)
cpp:
- // Saliency.cpp: implementation of the Saliency class.
- //
- //
- //===========================================================================
- // Copyright (c) 2009 Radhakrishna Achanta [EPFL]
- //===========================================================================
- #include "Saliency.h"
- #include <cmath>
- //
- // Construction/Destruction
- //
- Saliency::Saliency()
- {
- }
- Saliency::~Saliency()
- {
- }
- //===========================================================================
- /// RGB2LAB
- //===========================================================================
- void Saliency::RGB2LAB(
- const vector<unsigned int>& ubuff,
- vector<double>& lvec,
- vector<double>& avec,
- vector<double>& bvec)
- {
- int sz = int(ubuff.size());
- lvec.resize(sz);
- avec.resize(sz);
- bvec.resize(sz);
- for( int j = 0; j < sz; j++ )
- {
- int r = (ubuff[j] >> 16) & 0xFF;
- int g = (ubuff[j] >> 8) & 0xFF;
- int b = (ubuff[j] ) & 0xFF;
- double xval = 0.412453 * r + 0.357580 * g + 0.180423 * b;
- double yval = 0.212671 * r + 0.715160 * g + 0.072169 * b;
- double zVal = 0.019334 * r + 0.119193 * g + 0.950227 * b;
- xval /= (255.0 * 0.950456);
- yval /= 255.0;
- zVal /= (255.0 * 1.088754);
- double fX, fY, fZ;
- double lval, aval, bval;
- if (yval > 0.008856)
- {
- fY = pow(yval, 1.0 / 3.0);
- lval = 116.0 * fY - 16.0;
- }
- else
- {
- fY = 7.787 * yval + 16.0 / 116.0;
- lval = 903.3 * yval;
- }
- if (xval > 0.008856)
- fX = pow(xval, 1.0 / 3.0);
- else
- fX = 7.787 * xval + 16.0 / 116.0;
- if (zVal > 0.008856)
- fZ = pow(zVal, 1.0 / 3.0);
- else
- fZ = 7.787 * zVal + 16.0 / 116.0;
- aval = 500.0 * (fX - fY)+128.0;
- bval = 200.0 * (fY - fZ)+128.0;
- lvec[j] = lval;
- avec[j] = aval;
- bvec[j] = bval;
- }
- }
- //==============================================================================
- /// GaussianSmooth
- ///
- /// Blur an image with a separable binomial kernel passed in.
- //==============================================================================
- void Saliency::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;
- //--------------------------------------------------------------------------
- // Blur in the x direction.
- //---------------------------------------------------------------------------
- { 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++;
- }
- }}
- //--------------------------------------------------------------------------
- // Blur in the y direction.
- //---------------------------------------------------------------------------
- { 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++;
- }
- }}
- }
- //===========================================================================
- /// GetSaliencyMap
- ///
- /// Outputs a saliency map with a value assigned per pixel. The values are
- /// normalized in the interval [0,255] if normflag is set true (default value).
- //===========================================================================
- void Saliency::GetSaliencyMap(
- const vector<unsigned int>& 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);
- RGB2LAB(inputimg, lvec, avec, bvec);
- //--------------------------
- // Obtain Lab average values
- //--------------------------
- 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);
- //----------------------------------------------------
- // The kernel can be [1 2 1] or [1 4 6 4 1] as needed.
- // The code below show usage of [1 2 1] kernel.
- //----------------------------------------------------
- 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);
- }
- }
关于代码的使用说明:
- This file explains the usage of Saliency.h and Saliency.cpp files. The former contains the declaration of the Saliency class and its member functions and the later contains the respective definitions.
- Sample usage:
- #include "Saliency.h"
- void main()
- {
- // Assume we already have an unsigned integer buffer inputImg of
- // inputWidth and inputHeight (in row-major order).
- // Each unsigned integer has 32 bits and contains pixel data in ARGB
- // format. I.e. From left to right, the first 8 bits contain alpha
- // channel value and are not used in our case. The next 8 bits
- // contain R channel value; the next 8 bits contain G channel value;
- // the last 8 bits contain the B channel value.
- //
- // Now create a Saliency object and call the GetSaliencyMap function on it.
- Saliency sal;
- vector<double> salmap(0);
- sal.GetSaliencyMap(inputImg, inputWidth, inputHeight, salmap);
- // salmap is a floating point output (in row major order)
- }
我自己写的测试主程序:
可以指定一个文件夹,程序保存该文件夹下所有jpg文件的处理结果
- #include "Saliency.h"
- #include <cv.h>
- #include <cxcore.h>
- #include <highgui.h>
- #include "windows.h"
- #include <iostream>
- #include <cassert>
- using namespace std;
- int main(int argc,char** argv)
- {
- WIN32_FIND_DATAA FileData;
- HANDLE hFind;
- hFind = FindFirstFileA((LPCSTR)"Imgs/*.jpg",&FileData);
- if (hFind == INVALID_HANDLE_VALUE) {
- printf ("Invalid File Handle. GetLastError reports %d/n",
- GetLastError ());
- return (0);
- }
- Saliency sal;
- vector<double> salmap(0);
- while (FindNextFileA(hFind, &FileData)) {
- cout<<FileData.cFileName<<endl;
- string name("Imgs/");
- name.append(FileData.cFileName);
- IplImage* img=cvLoadImage(name.c_str());
- if (!img) {
- cout<<"failed to load image"<<endl;
- break;
- }
- assert(img->nChannels==3);
- vector<unsigned int >imgInput;
- vector<double> imgSal;
- //IplImage to vector
- for (int h=0;h<img->height;h++) {
- unsigned char*p=(unsigned char*)img->imageData+h*img->widthStep;
- for (int w=0;w<img->width;w++) {
- unsigned int t=0;
- t+=*p++;
- t<<=8;
- t+=*p++;
- t<<=8;
- t+=*p++;
- imgInput.push_back(t);
- }
- }
- sal.GetSaliencyMap(imgInput, img->width, img->height, imgSal);
- //vector to IplImage
- int index=0;
- IplImage* imgout=cvCreateImage(cvGetSize(img),IPL_DEPTH_64F ,1);
- for (int h=0;h<imgout->height;h++) {
- double*p=(double*)(imgout->imageData+h*imgout->widthStep);
- for (int w=0;w<imgout->width;w++) {
- *p++=imgSal[index++];
- }
- }
- name.append(".saliency.jpg");
- cvSaveImage(name.c_str(),imgout);
- cvReleaseImage(&img);
- cvReleaseImage(&imgout);
- }
- FindClose(&hFind);
- return 0;
- }
该代码的主页:http://ivrg.epfl.ch/supplementary_material/RK_ICIP2010/index.html
清华的最新研究:http://cg.cs.tsinghua.edu.cn/people/~cmm/saliency/