Chinaunix首页 | 论坛 | 博客
  • 博客访问: 428343
  • 博文数量: 53
  • 博客积分: 6243
  • 博客等级: 大校
  • 技术积分: 567
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-08 18:00
文章分类

全部博文(53)

文章存档

2013年(1)

2011年(20)

2010年(28)

2007年(3)

2006年(1)

分类: C/C++

2013-01-03 17:24:24

    这几天是元旦假期,正好有时间写个实验程序验证一下新想法。原来写的这个 “用局部边沿方向特征做图像识别目标检测” 检测效果还好,但是速度比较慢。这次的新算法可以快速计算图像的局部边沿方向。新算法首先计算图像的积分图,然后根据积分图计算图像的近似梯度场,在图像的边沿上梯度方向是法线方向,切线方向就是图像的局部边沿方向,这个算法比原来基于卷积的边沿方向算法快很多。

    图像的近似梯度场图:


求近似梯度场的算法:

点击(此处)折叠或打开

  1. inline HaarGradient img_haar_gradient_l4(IplImage *img_gray, CvMat* mat_Integral, CvPoint p)
  2. {
  3.         int l = 4;

  4.         double fix01,fix02,fix03,fix04;

  5.         double sum;

  6.         int x,y;

  7.         sum=0.0;
  8.         x = p.x - l;
  9.         y = p.y - l;
  10.         float ve = CV_IMAGE_ELEM(img_gray, uchar, y, x);
  11.         sum+=ve;
  12.         ve = CV_IMAGE_ELEM(img_gray, uchar, y, x+1);
  13.         sum+=ve;
  14.         ve = CV_IMAGE_ELEM(img_gray, uchar, y+1, x);
  15.         sum+=ve;
  16.         ve = CV_IMAGE_ELEM(img_gray, uchar, y+1, x+1);
  17.         sum+=ve;
  18.         fix01 = sum;

  19.         sum=0.0;
  20.         x = p.x - l;
  21.         y = p.y + l;
  22.         ve = CV_IMAGE_ELEM(img_gray, uchar, y, x);
  23.         sum+=ve;
  24.         ve = CV_IMAGE_ELEM(img_gray, uchar, y, x+1);
  25.         sum+=ve;
  26.         ve = CV_IMAGE_ELEM(img_gray, uchar, y-1, x);
  27.         sum+=ve;
  28.         ve = CV_IMAGE_ELEM(img_gray, uchar, y-1, x-1);
  29.         sum+=ve;
  30.         fix02 = sum;

  31.         sum=0.0;
  32.         x = p.x + l;
  33.         y = p.y + l;
  34.         ve = CV_IMAGE_ELEM(img_gray, uchar, y, x);
  35.         sum+=ve;
  36.         ve = CV_IMAGE_ELEM(img_gray, uchar, y, x-1);
  37.         sum+=ve;
  38.         ve = CV_IMAGE_ELEM(img_gray, uchar, y-1, x);
  39.         sum+=ve;
  40.         ve = CV_IMAGE_ELEM(img_gray, uchar, y-1, x-1);
  41.         sum+=ve;
  42.         fix03 = sum;

  43.         sum=0.0;
  44.         x = p.x + l;
  45.         y = p.y - l;
  46.         ve = CV_IMAGE_ELEM(img_gray, uchar, y, x);
  47.         sum+=ve;
  48.         ve = CV_IMAGE_ELEM(img_gray, uchar, y, x-1);
  49.         sum+=ve;
  50.         ve = CV_IMAGE_ELEM(img_gray, uchar, y+1, x);
  51.         sum+=ve;
  52.         ve = CV_IMAGE_ELEM(img_gray, uchar, y+1, x-1);
  53.         sum+=ve;
  54.         fix04 = sum;


  55.         HaarGradient grad;

  56.         int x1 = p.x - l, x2 = p.x;
  57.         int y1 = p.y - l, y2 = p.y + l;

  58.         float *p_x1y1,*p_x1y2,*p_x2y1,*p_x2y2;
  59.         double inte_x1y1,inte_x1y2,inte_x2y1,inte_x2y2;

  60.         p_x1y1 = (float*)cvPtr2D(mat_Integral, y1, x1);
  61.         p_x1y2 = (float*)cvPtr2D(mat_Integral, y2, x1);
  62.         p_x2y1 = (float*)cvPtr2D(mat_Integral, y1, x2);
  63.         p_x2y2 = (float*)cvPtr2D(mat_Integral, y2, x2);

  64.         double inte_xy01 = *p_x2y2 - *p_x1y2 - *p_x2y1 + *p_x1y1 - fix01 - fix02;

  65.         x1 = p.x, x2 = p.x + l;
  66.         y1 = p.y - l, y2 = p.y + l;


  67.         p_x1y1 = (float*)cvPtr2D(mat_Integral, y1, x1);
  68.         p_x1y2 = (float*)cvPtr2D(mat_Integral, y2, x1);
  69.         p_x2y1 = (float*)cvPtr2D(mat_Integral, y1, x2);
  70.         p_x2y2 = (float*)cvPtr2D(mat_Integral, y2, x2);

  71.         double inte_xy02 = *p_x2y2 - *p_x1y2 - *p_x2y1 + *p_x1y1 - fix03 - fix04;

  72.         double haar_horizontal = inte_xy01 - inte_xy02;

  73.         x1 = p.x - l, x2 = p.x + l;
  74.         y1 = p.y - l, y2 = p.y;

  75.         *p_x1y1,*p_x1y2,*p_x2y1,*p_x2y2;
  76.         inte_x1y1,inte_x1y2,inte_x2y1,inte_x2y2;

  77.         p_x1y1 = (float*)cvPtr2D(mat_Integral, y1, x1);
  78.         p_x1y2 = (float*)cvPtr2D(mat_Integral, y2, x1);
  79.         p_x2y1 = (float*)cvPtr2D(mat_Integral, y1, x2);
  80.         p_x2y2 = (float*)cvPtr2D(mat_Integral, y2, x2);

  81.         inte_xy01 = *p_x2y2 - *p_x1y2 - *p_x2y1 + *p_x1y1 - fix01 - fix04;

  82.         x1 = p.x - l, x2 = p.x + l;
  83.         y1 = p.y, y2 = p.y + l;


  84.         p_x1y1 = (float*)cvPtr2D(mat_Integral, y1, x1);
  85.         p_x1y2 = (float*)cvPtr2D(mat_Integral, y2, x1);
  86.         p_x2y1 = (float*)cvPtr2D(mat_Integral, y1, x2);
  87.         p_x2y2 = (float*)cvPtr2D(mat_Integral, y2, x2);

  88.         inte_xy02 = *p_x2y2 - *p_x1y2 - *p_x2y1 + *p_x1y1 - fix02 - fix03;

  89.         double haar_vertical = inte_xy02 - inte_xy01;

  90.         double haar_vh = fabs(haar_vertical/haar_horizontal);

  91.         //grad.angle = atan2(haar_vertical, haar_horizontal);
  92.         grad.angle = (CV_PI/2.0 * haar_vh) / (1.0 + haar_vh); //(pi/2 * y) / (1 + y)

  93.         if (haar_vertical < 0.0 && haar_horizontal < 0.0) grad.angle += CV_PI;

  94.         if (haar_vertical < 0.0 && haar_horizontal > 0.0) grad.angle = 2*CV_PI - grad.angle;

  95.         if (haar_vertical > 0.0 && haar_horizontal < 0.0) grad.angle = CV_PI - grad.angle;

  96.         //if (haar_vertical < 0.0) grad.angle += CV_PI;

  97.         grad.mod = sqrt(haar_vertical*haar_vertical + haar_horizontal*haar_horizontal);

  98.         if (p.x == 50 && p.y == 50)
  99.         {
  100.                 std::cout << "haar_vertical, haar_horizontal " << haar_vertical << ", " << haar_horizontal << std::endl;
  101.                 std::cout << " haar_vh = " << haar_vh;
  102.                 std::cout << " ang = " << grad.angle/CV_PI * 180.0 << std::endl;
  103.         }

  104.         return grad;
  105. }
根据梯度可以得到局部边沿方向图,和原来的基于卷积的算法结果一致。


  这样特征提取问题就解决了,下一步还要改进匹配算法,提高匹配效率,加强匹配算法的弹性适应一定的视角变化,试试分组投票等算法,不过元旦假期马上就结束了,只能以后放假再说了,估计春节假期能写完新程序。

                                                                  2013.01.03
                                                                   zhujiang
阅读(3699) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~