[转]国外的一个图像显著区域检测代码及其效果图 saliency region detection

来源:互联网 发布:淘宝假冒品牌退款 编辑:程序博客网 时间:2024/05/19 22:27

http://blog.csdn.net/onezeros/archive/2011/04/03/6299745.aspx

原创  国外的一个图像显著区域检测代码及其效果图 saliency region detection

先看几张效果图吧

效果图:

可以直接测试的代码:

头文件:

// Saliency.h: interface for the Saliency class.  
//  
//////////////////////////////////////////////////////////////////////  
//===========================================================================  
//  Copyright (c) 2009 Radhakrishna Achanta [EPFL]   
//===========================================================================  
  
#if !defined(_SALIENCY_H_INCLUDED_)  
#define _SALIENCY_H_INCLUDED_  
  
#include   
#include   
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   
  
  
//////////////////////////////////////////////////////////////////////  
// 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);  
    }  
} 
关于代码的使用说明:
#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   
#include   
#include   
  
#include "windows.h"  
  
#include   
#include   
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<    
        string name("Imgs/");  
        name.append(FileData.cFileName);  
        IplImage* img=cvLoadImage(name.c_str());  
        if (!img) {  
            cout<<"failed to load image"<    
            break;  
        }  
        assert(img->nChannels==3);  
          
        vector<unsigned int >imgInput;  
        vector<double> imgSal;  
        //IplImage to vector  
        for (int h=0;hheight;h++) {  
            unsigned char*p=(unsigned char*)img->imageData+h*img->widthStep;  
            for (int w=0;wwidth;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;hheight;h++) {  
            double*p=(double*)(imgout->imageData+h*imgout->widthStep);  
            for (int w=0;wwidth;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/

原创粉丝点击