目标检测之显著区域检测---国外的一个图像显著区域检测代码及其效果图 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 <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/

http://blog.csdn.net/onezeros/article/details/6299745#comments

时间: 2024-10-15 06:53:32

目标检测之显著区域检测---国外的一个图像显著区域检测代码及其效果图 saliency region detection的相关文章

【计算机视觉】借助图像直方图来检测特定物(MeanShift、CamShift算法)

直方图引入 直方图是一个简单的表,它给出了一幅图像或一组图像中拥有给定数值的像素数量.因此,灰度图像的直方图有256个条目(或称为容器).0号容器给出值为0的像素数目,1号容器给出值为1的像素个数,以此类推. 直方图反投影 直方图是图像内容的一个重要特性.如果一幅图像的区域中显示的是一种独特的纹理或是一个独特的物体,那么这个区域的直方图可以看做一个概率函数,它给出的是某个像素属于该纹理或物体的概率.这使得我们可以借助图像的直方图来检测特定的内容. 反投影直方图的方法是一种把目标概率分布映射到观测

『cs231n』图像定位与检测(下,待续)

图像检测原理 定义: 给出一张图片和几个类别,定位出图片中这些类所有的实例. 思路分析:回归vs分类 由于输出数目不定,所以不能简单的把检测任务像定位任务一样归化为回归任务(检测任务会导致回归层神经元数目是不确定的) 在机器学习中,分类和回归是解决所有问题的两种基本思路,所以我们尝试用分类的思想分析问题. 思路是将所有可能分类的区域送入网络 问题是图片数量太多 直观的解决思路是换个速度快的电脑... ... 实际上新电脑还是不够快... ... 那就只查看一些可能的区域(预处理) Region

图像局部特征点检测算法综述与应用举例

研究图像特征检测已经有一段时间了,图像特征检测的方法很多,又加上各种算法的变形,所以难以在短时间内全面的了解,只是对主流的特征检测算法的原理进行了学习.总体来说,图像特征可以包括颜色特征.纹理特等.形状特征以及局部特征点等.其中局部特点具有很好的稳定性,不容易受外界环境的干扰,本篇文章也是对这方面知识的一个总结. 本篇文章现在(2015/1/30)只是以初稿的形式,列出了主体的框架,后面还有许多地方需要增加与修改,例如2013年新出现的基于非线性尺度空间的KAZE特征提取方法以及它的改进AKAT

paper 27 :图像/视觉显著性检测技术发展情况梳理(Saliency Detection、Visual Attention)

1. 早期C. Koch与S. Ullman的研究工作. 他们提出了非常有影响力的生物启发模型. C. Koch and S. Ullman . Shifts in selective visual attention: Towards the underlying neural circuitry. Human Neurobiology, 4(4):219-227, 1985. C. Koch and T. Poggio. Predicting the Visual World: Silenc

图像肤色初步检测实现

肤色检测输出结果中有许多瑕疵,待于进一步处理(如:滤波操作.....).在此贴出几种图像肤色检测相关代码,供大家参考. 第一种:RGB color space // skin region location using rgb limitation void ImageSkin::ImageSkinRGB(IplImage* rgb,IplImage* _dst) { assert(rgb->nChannels==3&& _dst->nChannels==3); static

四种比较简单的图像显著性区域特征提取方法原理及实现-----&gt; AC/HC/LC/FT。

laviewpbt  2014.8.4 编辑 Email:[email protected]   QQ:33184777 最近闲来蛋痛,看了一些显著性检测的文章,只是简单的看看,并没有深入的研究,以下将研究的一些收获和经验共享. 先从最简单的最容易实现的算法说起吧: 1. LC算法 参考论文:Visual Attention Detection in Video Sequences Using Spatiotemporal Cues. Yun Zhai and Mubarak Shah.  Pa

四种简单的图像显著性区域特征提取方法-----&gt; AC/HC/LC/FT。

四种简单的图像显著性区域特征提取方法-----> AC/HC/LC/FT. 分类: 图像处理 2014-08-03 12:40 4088人阅读 评论(4) 收藏 举报 salient region detec显著性检测 laviewpbt  2014.8.3 编辑 Email:[email protected]   QQ:33184777 最近闲来蛋痛,看了一些显著性检测的文章,只是简单的看看,并没有深入的研究,以下将研究的一些收获和经验共享.      先从最简单的最容易实现的算法说起吧: 1

简单的图像显著性区域特征提取方法-----opencv实现LC,AC,FT

https://blog.csdn.net/cai13160674275/article/details/72991049?locationNum=7&fps=1 四种简单的图像显著性区域特征提取方法-----> AC/HC/LC/FT. 上文讲了几种简单的方法,显著性检测就是把一幅图像中最吸引人注意的部分提取出来. 我用opencv重写了LC,AC,FT三种算法,代码和效果如下: 利用频谱来做的显著性提取的方式 1.,后面的方法其实大概都是基于这个实现的,代码样子差不多 LC思路就是利用对

ACM 图像有用区域

图像有用区域 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 “ACKing”同学以前做一个图像处理的项目时,遇到了一个问题,他需要摘取出图片中某个黑色线圏成的区域以内的图片,现在请你来帮助他完成第一步,把黑色线圏外的区域全部变为黑色.       图1                                                        图2 已知黑线各处不会出现交叉(如图2),并且,除了黑线上的点外,图像中没有纯黑色(即像素为0的点).