常见的特征提取

来源:互联网 发布:c语言驱动开发 编辑:程序博客网 时间:2024/05/16 18:16

在图像处理中常用的特征:

边缘:使用最多的:sobel canny susan


sobel:这个还可以来求梯度方向

void sobel_te(IplImage *img,IplImage * sobel8u)
{
IplImage*  sobel=cvCreateImage( cvGetSize(img), IPL_DEPTH_16S, 1 );
IplImage* sobel_y=cvCreateImage( cvGetSize(img), IPL_DEPTH_16S, 1 );
IplImage* sobel_x=cvCreateImage( cvGetSize(img), IPL_DEPTH_16S, 1 );
cvSobel(img,sobel_y,1,0,3);  //提取Y方向
cvSobel(img,sobel_x,1,0,3);  //提取X方向
cvOr(sobel_x,sobel_y,sobel,NULL);   
cvConvertScaleAbs(sobel,sobel8u,1,0);//把sobel计算后的值由16位转为8位供正常显示 
sobel8u->origin = img->origin;    
}

susan:这是在网上找到的,注意边缘检测后再显示中图像会和正常的不太一样,调用该函数的时候实参nimg,最好cvcloneimg后再做。

void :susan_bianyuan(const IplImage *Img,IplImage * nimg)
{
int height ,width ,step ,channels ;
int i,j,k,same ,max,min,thresh,sum;
uchar*data0,*data1 ;
height = Img->height;
width = Img->width;
step  = Img->widthStep/sizeof(uchar);
channels = Img->nChannels;
data0   = (uchar*)Img->imageData;
data1 =  (uchar*)nimg->imageData;
int OffSetX[37] = { -1, 0, 1,
-2,-1, 0, 1, 2,
-3,-2,-1, 0, 1, 2, 3,
-3,-2,-1, 0, 1, 2, 3,
-3,-2,-1, 0, 1, 2, 3,
-2,-1, 0, 1, 2,
-1, 0, 1 };
int OffSetY[37] = { -3,-3,-3,
-2,-2,-2,-2,-2,
-1,-1,-1,-1,-1,-1,-1,
0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2,
3, 3, 3 };

max = min = data0[0];
for(i=3;i<height-3;i++)
for(j=3;j<width-3;j++)
{
same =0;sum = 0;
for(k=0;k<37;k++)
{
sum+=data0[(i+OffSetY[k])*step+(j+OffSetX[k])];
thresh = sum/37;
if(abs(data0[(i+OffSetY[k])*step+(j+OffSetX[k])]-data0[i*step+j])<=thresh)
same++;
if(same<30)//30
data1[i*step+j] = 255;
else
data1[i*step+j] = 0;
}
}

}

oid susan_jiaodian(IplImage *src,IplImage *dst)
{


IplImage *pImgGray=NULL;
CvMat *mat_I,*mat_Num,*mat_R,*mat_corner;
int size=7;
pImgGray=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
::cvCopy(src,pImgGray,0);
const int cxDIB=src->width ;         // 图像宽度
const int cyDIB=src->height;         // 图像高度
double *I=new double[cxDIB*cyDIB];
int i,j;
for(j=0;j<cyDIB;j++)
for(i=0;i<cxDIB;i++)
{
I[j*cxDIB+i]=S(pImgGray,i,j);//将灰度图像数值存入I中
}
mat_I=cvCreateMat(cyDIB,cxDIB,CV_64FC1);
cvInitMatHeader(mat_I,cyDIB,cxDIB,CV_64FC1,I);//用I来初始化相应的矩阵
mat_Num=mbnum(mat_I,cxDIB,cyDIB,size);//用来求得n(r0)
mat_R=mbr(mat_Num,cxDIB,cyDIB,size,1.0);//get the R(r0)
mat_corner=mbcorner(mat_R,cxDIB,cyDIB,size);//get the corner matrix


CvPoint pt;
for(j=size/2;j<cyDIB-size/2;j++)  //ignore the edge pixels from the size/2 to DIB-size/2
for(i=size/2;i<cxDIB-size/2;i++)
{
if(CV_MAT_ELEM(*mat_corner,int,j,i)==255){
pt.x=i;
pt.y=j;
cvCircle(dst,pt,2,CV_RGB(255,0,0),1,8,0); //draw a circl on the src when it is a corner
}
}

cvReleaseImage(&pImgGray);
cvReleaseMat(&mat_I);
cvReleaseMat(&mat_Num);
cvReleaseMat(&mat_R);
cvReleaseMat(&mat_corner);
}


轮廓/hu不变矩:利用opencv中cvFindContours,可以得到hu不变矩

CvSeq*lunkuo(IplImage* src)
{

IplImage* img= cvCreateImage(cvSize(mframe->width,mframe->height),IPL_DEPTH_8U,1);
cvCopy(src,img,0);
         CvMemStorage*storage = cvCreateMemStorage(0);
         CvSeq*contour = 0;
         // 提取轮廓cvFindContours会改变第一个参数img的内容的,所以不想改变,前面用了cvcopy
         intcontour_num = cvFindContours(img, storage, &contour, sizeof(CvContour),CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);//CV_RETR_CCOMP  
         CvSeq*_contour = contour; 
         doublemaxarea = 0;
         doubleminarea =200;      double len1=0;
         CvMoments*moments1=new CvMoments(); 
         CvHuMoments*huMonents1=new CvHuMoments();

         for(inti=1; contour != 0; contour = contour->h_next,i++ )  
         { 


                   doubletmparea = fabs(cvContourArea(contour));

                   if(tmparea< minarea)   
                   { 
                   cvSeqRemove(contour,0); // 删除面积小于设定值的轮廓
                   continue;
                   }
                   CvRectaRect = cvBoundingRect( contour, 0 ); 
                  
                   if((aRect.width/aRect.height)<1)  
                   { 
                   cvSeqRemove(contour,0); //删除宽高比例小于设定值的轮廓
                   continue;
                   }

                   if(tmparea> maxarea)  
                   { 
                            maxarea= tmparea;
                   } 
                   //创建一个色彩值
                   CvScalarcolor = CV_RGB( 0, 255, 255 );
cvRectangle( temp, cvPoint( aRect.x, aRect.y),cvPoint( aRect.x + aRect.width, aRect.y + aRect.height ),CV_RGB(0,255,255),3,8,0);
                   CvBox2D rect=cvMinAreaRect2 (contour,0)
                   //cout<<"轮廓数:"<<contour_num<<"面积"<<tmparea<<"周长"<<len1<<endl;
                   //轮廓的矩 
                   cvMoments(contour,moments1,0);
                   //Hu矩
                   cvGetHuMoments(moments1,huMonents1);
         } 


         deletemoments1;
         delete huMonents1;

return contour ;

}

Hu不变矩:

是描述图像的几何特征,由于Hu不变矩只用到低阶矩(最多也就用到三阶矩),对于图像的细节未能很好的描述出来。

Zernike矩 

在模式识别中,一个重要的问题是对目标的方向性变化也能进行识别。Zernike 矩是一组正交矩,具有旋转不变性的特性,即旋转目标并不改变其模值。

由于Zernike 矩可以构造任意高阶矩,所以Zernike 矩的识别效果优于其他方法.所以在文献中关于船舶识别的多采用几何矩 Zernike矩,


轮廓匹配:cvMatchShapes

项目中用到:可以将前面得到的轮廓 CvSeq*contour 输入到cvMatchShapes中进行匹配。

IplImage *srcColor = cvLoadImage("E:\\vs上级程序(自己的)\\vs练习\\跟踪程序\\vv\\detect\\ship\\n11\\6.jpg", 1);  
CvSeq * c1=lunkuo(srcColor);
int i;  
stringstream ss;  
string path;  
string str;  
IplImage *dst = NULL, *dstColor;  
char c[256];  
double result, maxResult= 1000 * 256 *256;  
IplImage *resultMap = NULL;  
for (i =1; i <=6; i ++)  
{  
path = "E:\\n11\\";  
ss.clear();  
ss << i;  
ss >> str;  
str += ".jpg";  
path += str;  
ss.clear();  
ss << path;  
ss >> c;  
dstColor = cvLoadImage(c,1);  
if(dstColor){
CvSeq * c2=lunkuo(dstColor);
result = cvMatchShapes(c1, c2, 3);  
cout<<result<<endl;
if(result <Minresult)  
{  
resultMap = cvCreateImage(cvGetSize(dstColor), 8, 3);  
MinResult = result;  
cvCopy(dstColor, resultMap,0);  
}  
}
}  

 直线:

void find_lines(IplImage* src,IplImage* dst)
{

CvMemStorage* storage = cvCreateMemStorage(0);  
CvSeq* lines = 0;  
lines = cvHoughLines2( src, storage, CV_HOUGH_PROBABILISTIC, 6, CV_PI/180, 50, 50, 10 );
int num_lines=0;
//printf("直线个数:",lines->total);
for(int i = 0; i < lines->total; i++ )
{
CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
float rho = line[0].x;
float theta = line[1].y;
float result=(line[0].x-line[1].x)*(line[0].x-line[1].x)+(line[0].y-line[1].y)*(line[0].y-line[1].y);
if(result>100){
//printf("%f\n",result);
cvLine( dst, line[0], line[1], CV_RGB(255,0,0),6, CV_AA, 0 );
}
}
cvReleaseMemStorage(&storage);

}

纹理特征:

灰度共生矩阵,LBP (局部二值模式),LTP(局部三值模式)在做跟踪的时候很多文献将LBP.LTP加入到Meanshift算法中。灰度共生矩阵在识别中多采用


     

0 0
原创粉丝点击