c++中的Mean shift实现



谁能推荐一个轻量级的c++ mean shift集群实现?我已经在使用OpenCV,但是他们的mean shift实现是用于跟踪,而不是集群。我见过EDISON,但是,这是用于图像分割而不是聚类。

我可以自己实现它,但是我宁愿不投入时间,也不愿冒bug的风险。

谢谢

这是旧的,但我现在正在与mean shift工作,所以我认为最好回答。

我想我理解你在这里所做的区别,但是当你说你正在寻找模式检测时,从算法的角度来看,这在技术意义上是模糊的,因为算法本质上是用于搜索"模式",这是局部最小值或最大值,取决于你如何构建优化问题(梯度下降或上升)。

这个在EDISON网站上找到的源码,声称是mean shift聚类算法的c++实现,但正如上面所讨论的,聚类是模式搜索行为的主要实现,而其他所有mean shift的使用都是基于这种行为,尤其是分割,所以你当然可以使用EDISON源码来找到一个聚类实现,即使你必须搜索它一点。

我也发现了这个Github项目,因为它是值得的,但我以前没有使用过它。

最后注意:我还注意到你说的"轻量级"实现。注意,均值移位不是一个非常有效的算法(我认为它是O(N^3),但我会检查一下)。也就是说,它仍然可以有效地实施,尽管如何衡量这一点更加模糊。毋庸置疑,Quick Shift, UCLA研究人员试图解决更有效的medioid Shift问题,一个类似的非参数模式搜索算法,可能更像你在"轻量级"算法中寻找的东西。

这是我的c++版本的mean shift对象跟踪方法。要成功运行代码,需要将tf.h头文件添加到主代码目录中。

#include "tf.h" // include the header file
using namespace cv;
using namespace std;
#include <stdio.h>
makerect mkr;  // rectangle for encompassing target 
// rcs for row coordination of target window center
//ccs for column coordination of target window center
double rcs=0,ccs=0; 
// w for width of target window 
// l for length of target window
double W=70,L=60;
const int mySizes[3]={16,16,16}; // vector for number of histogram bins
cv::Mat q4hsv = Mat::zeros(3,mySizes,CV_64F); // initializing histogram variable
uchar nbins=16; // var for num of histogram bins
int main(void){     
    printf("enter 14 or 36: t"); // enter number of input video name
    uint flag; // var for video flag or number
    cin>>flag;
    Mat ref4frame; // reference frame which is used for initializing mean shift parameters
char filename [50]; 
sprintf(filename,"im%d.avi",flag);
VideoCapture capture(filename);
if( !capture.isOpened() )
    throw "Error when reading steam_avi";
unsigned long int f4counter=0; // frame counter var
histhsv hsv; // instantiating histhsv class
for (f4counter=1;f4counter<=40000000;f4counter++){ // a big number to support many frames
    capture >> ref4frame; //reading input image from specified directory
    if( !(ref4frame.data ))   // checking the read status
    {       
       printf("Cannot load file image %sn", filename);    
        break;    } 
    uchar ndiv = uchar(256/nbins); // division value to which intesity values are divided
if (f4counter==1)   { // special for 1st frame
    char modelname[20];
    if(flag==36){
    sprintf(modelname,"data%d.png",flag);       
    }
    else if (flag==14){
        sprintf(modelname,"data%d.jpg",flag);   
    }
    // imread is defined in tf.h
    Mat img = imread(modelname,1);//reads 1st image
    if( !(img.data ))//check if file loading is ok
    {       
       printf("Cannot load file image %sn", modelname);       
        break;    } 
    hsv.img=img;//assign new image to hsv object (calculates hsv or rgb hist)
    hsv.run();//run the histogram calculator
// assign temporary hsv object to reference hist q4hsv object
for (int i=0;i<16;i++){
        for(int j=0;j<16;j++){
            for(int k=0;k<16;k++){
                q4hsv.at<double>(i,j,k)=hsv.q[i][j][k];
            }
        }
}
}
if(f4counter<5){averageglobalhsv(ref4frame,q4hsv,rcs,ccs);}
averagelocalhsv(ref4frame,q4hsv,rcs,ccs);//normalizing histogram values (0-1)
    Point pt1; pt1.x=ccs; pt1.y=rcs;
    int thickness=4;//thickness of marker - here is a circle
    int lineType=8;
    int shift=0;
    RNG rng(0xFFFFFFFF);
    cv::circle(ref4frame, pt1, 5, randomColor(rng), thickness, lineType,
shift); //marking object center with a circle
    myimshow("reference frame",ref4frame);//show current image
    waitKey(1); 
}
int c=waitKey(0);
//release memory
ref4frame.release();
destroyAllWindows();
    return 0;
}

下面是tf.h头文件的内容:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2opencv.hpp"
#include "corecore.hpp"
#include <cstdio>
#include <iostream>
#include <fstream>
#include <math.h>
using namespace cv;
using namespace std;
// makerect class: to create the desired size encompassing window
class makerect
{
public:
    double rcs,ccs,w,l; // ctl row, ctl column, width, length
    uint rmin,rmax,cmin,cmax,height,length;//min max coordination vars
    void run(void);
    makerect();
};
makerect::makerect(){
    rmin=0;rmax=0;cmin=0;cmax=0;rcs=0;ccs=0;w=0;l=0;
}
void makerect::run(){
//not that all points must be either integer or floating point
    rmin=uint(rcs-floor(w/2));//min row coordination
    rmax=uint(rmin+w);//max row coordination
    cmin=uint (ccs-floor(l/2));//min column coordination
    cmax=uint(cmin+l);//max column coordination
    if(cmax>length){cmax=length;cmin=cmax-l;// checking column to be inside image}
    if(rmax>height){rmax=height;rmin=rmax-w;//checking row to be inside image}
}
static Scalar randomColor(RNG& rng)
{
    int icolor = (unsigned)rng;
    return Scalar(icolor&255, (icolor>>8)&255, (icolor>>16)&255);
}
//myimshow: is a function to to show image
void myimshow(char* name4window,Mat &tmp4image){
    namedWindow(name4window,1); imshow(name4window,tmp4image);
}

void averageglobalhsv(Mat ref4frame,Mat &f,double &rcs,double &ccs)
{
    Mat img;
    cvtColor(ref4frame,img,CV_BGR2HSV);//rgb2hsv conversion
    uint n4rowsref=ref4frame.rows;// num of rows
    uint n4colsref=ref4frame.cols;// num of cols
    double *im4bp = new double [n4rowsref*n4colsref];//1-D dynamic array equal to image pixels
    uint nbins=16;// num of histogram bins
    uint ndiv=256/nbins; //division value to which intensities are divided
//vars for image moments (zero to second moments)
double m00=0,m01=0,m10=0,m20=0,m02=0,m11=0,w=0; 
uint R=0,G=0,B=0; //red bin num, green bin num, blue bin num
    for(uint i=0;i<n4rowsref;i++){ //loop through all image rows
        for(uint j=0;j<n4colsref;j++){//loop through all image columns
            Vec3b inten=img.at<Vec3b>(i,j);//a vector of three element
            R=inten.val[2]; G=inten.val[1];  B=inten.val[0];
            R/=ndiv; G/=ndiv;  B/=ndiv;//calculating the bin to which current pixel intensity belong
                im4bp[i*n4colsref+j]=1.3*sqrt(f.at<double>(R,G,B));//calculating spatial weighted kernel histogram formula
        }
    }
    for(uint i=0;i<n4rowsref;i++){//loop through all image rows
        for(uint j=0;j<n4colsref;j++){//loop through all image columns
            w=im4bp[j+n4colsref*i];// weight for pixel at (i,j)
            m01=m01+double(i)*w;//first moment on y/row coordination
            m10=m10+double(j)*w;//first moment on x/column coordination
            m00=m00+w;//zeroth moment which is sum of all moments
        }
    }
if(m00>0){  
rcs=ceil(m01/m00);//central point for row
ccs=ceil(m10/m00);}//central point for column
delete im4bp;//cleaning memory
}

void averagelocalhsv(Mat ref4frame,Mat &f,double &rcs,double &ccs)
{
    Mat img;
cvtColor(ref4frame,img,CV_BGR2HSV); 
makerect mkr;
int sz[]={2,2};
    uint n4rowsref=ref4frame.rows;
    uint n4colsref=ref4frame.cols;
    double *im4bp = new double [n4rowsref*n4colsref];
    uint nbins=16;
    uint ndiv=256/nbins;
double m00=0,m01=0,m10=0,m20=0,m02=0,m11=0,w=0,Dxx,Dyy,Dxy;
uint R=0,G=0,B=0;
    for(uint i=0;i<n4rowsref;i++){
        for(uint j=0;j<n4colsref;j++){
            Vec3b inten=img.at<Vec3b>(i,j);
            R=inten.val[2]; G=inten.val[1];  B=inten.val[0];
            R/=ndiv; G/=ndiv;  B/=ndiv;
            im4bp[i*n4colsref+j]=1.3*sqrt(f.at<double>(R,G,B));
        }
    }

for(int iter=1;iter<5;iter++){
    mkr.rcs=rcs;mkr.ccs=ccs;mkr.w=100;mkr.l=100;mkr.height=ref4frame.rows;
    mkr.length=ref4frame.cols;  mkr.run();
    m00=0;m01=0;m10=0;m20=0;m02=0;m11=0;
    for(uint i=mkr.rmin;i<mkr.rmax;i=i+1){
        for(uint j=mkr.cmin;j<mkr.cmax;j=j+1){
            w=im4bp[j+n4colsref*i];
            m01=m01+double(i)*w;
            m10=m10+double(j)*w;
            m00=m00+w;
        }
    }   
}
if(m00>0){
rcs=ceil(m01/m00);
ccs=ceil(m10/m00);
}
delete im4bp;
}
class histhsv{
public:
    histhsv();
    void run(void);
    Mat img;    
    double q[16][16][16];
};
histhsv::histhsv(){};
void histhsv::run(void){
//Mat hsv4image;
double sum4hist=0;
uchar nbins=16;
uchar ndiv=256/nbins;
double wmax =0;;    
double r_center=0;
double c_center =0;
r_center = img.rows/2;
c_center = img.cols/2;
for (int i=0;i<nbins;i++){for(int j=0;j<nbins;j++){for(int k=0;k<nbins;k++){
q[i][j][k]=0;   }   }   };
    cvtColor(img,img,CV_BGR2HSV);       
    int H=0,S=0,V=0;    
    for(int r=0;r<img.rows;r++){
        for(int c=0;c<img.cols;c++){
            Vec3b intensity = img.at<Vec3b>(r,c);
            H=intensity.val[0]/ndiv;
            S=intensity.val[1]/ndiv;
            V=intensity.val[2]/ndiv;
            q[H][S][V]+=wmax-(pow(r-r_center,2)+pow(c-c_center,2));
            sum4hist+=q[H][S][V];
        }
    }
    for (int i=0;i<nbins;i++){
        for(int j=0;j<nbins;j++){
            for(int k=0;k<nbins;k++){
                q[i][j][k]/=sum4hist;
            }
        }
    }       
}

相关内容

  • 没有找到相关文章