基于生长的棋盘格角点检测方法 代码介绍

#本文主要讲述代码同时丰富参考博客中的一些小点和问题
####参考文章:
https://blog.csdn.net/sunshine_zoe/article/details/78303658

####参考资料

1、论文
Geiger A, Moosmann F, Car Ö, et al. Automatic camera and range sensor calibration using a single shot[C]//Robotics and Automation (ICRA), 2012 IEEE International Conference on. IEEE, 2012: 3936-3943.

2、代码网站(我改了其中一些的顺序,增加了一些用于适应自己的情况)
http://www.cvlibs.net/software/libcbdetect/


直接上干货

代码块 MATLAB

增加地址(论文的代码里面没有的,适用于小白,地址需要改成自己的,增加的原因是有时候图片不能识别)

C:\Users\Administrator\Desktop\libcbdetect (1)\libcbdetect\matching

addpath('C:\Users\Administrator\Desktop\libcbdetect (1)\libcbdetect\matching');
addpath('C:\Users\Administrator\Desktop\libcbdetect (1)\libcbdetect\data');
I = imread('09.jpg');
demo.m分块:主要分为三大块。1.角点检测;2.棋盘格检测;3.画出来
corners =  findCorners(I,0.01,1);
chessboards = chessboardsFromCorners(corners);
plotChessboards(chessboards,corners);
findcorners.m
灰度转换
img = im2double(img);
if length(size(img))==3
  img = rgb2gray(img);
end
findCorners ::计算梯度的角度,归一化到【0,pi】;梯度强度,并归一化到【0,1】

Prewitt在X, Y方向上梯度算子分别为:
在这里插入图片描述

% sobel masks  卷积核
du = [-1 0 1; -1 0 1; -1 0 1];
dv = du';

% compute image derivatives (for principal axes estimation)
img_du     = conv2(double(img),du,'same');%卷积:对img进行du卷积,返回和img相同尺寸的卷积结果
img_dv     = conv2(double(img),dv,'same');%两个方向的梯度
img_angle  = atan2(img_dv,img_du);        %梯度方向
img_weight = sqrt(img_du.^2+img_dv.^2);   %梯度值

figure(1); imshow(img_weight); hold on;%%%%%%%%%%%%%%%1

% correct angle to lie in between [0,pi]
img_angle(img_angle<0)  = img_angle(img_angle<0)+pi;
img_angle(img_angle>pi) = img_angle(img_angle>pi)-pi;

% scale input image
img     = double(img);
img_min = min(img(:));
img_max = max(img(:));
img     = (img-img_min)/(img_max-img_min);
findCorners::滤波(其实就是参考博客中写到的8个角点模型,卷积)

这里我增加了一个radius(4) = 30;使他可以检测到中心点附近的(广角相机)角点
createCorrelationPatch这个函数就是其中4个模型,后面会通过case1和case2来增加对称性但是颜色相反的模型。
原程序:
原程序
修改之后:
修改之后

% 3 scales 后面会用到
radius(1) = 4;
radius(2) = 8;
radius(3) = 12;
radius(4) = 30;
% filter image
img_corners = zeros(size(img,1),size(img,2));
for template_class=1:size(template_props,1)
  
  % create correlation template 创建三个/四个尺寸的四个模板
  template = createCorrelationPatch(template_props(template_class,1),template_props(template_class,2),template_props(template_class,3));
  
  % filter image according with current template 滤波(上面的四个模板)
  img_corners_a1 = conv2(img,template.a1,'same');
  img_corners_a2 = conv2(img,template.a2,'same');
  img_corners_b1 = conv2(img,template.b1,'same');
  img_corners_b2 = conv2(img,template.b2,'same');
  
  % compute mean
  img_corners_mu = (img_corners_a1+img_corners_a2+img_corners_b1+img_corners_b2)/4;
  
  % case 1: a=white, b=black
  img_corners_a = min(img_corners_a1-img_corners_mu,img_corners_a2-img_corners_mu);%每个元素单独比较
  img_corners_b = min(img_corners_mu-img_corners_b1,img_corners_mu-img_corners_b2);
  img_corners_1 = min(img_corners_a,img_corners_b);
  
  % case 2: b=white, a=black
  img_corners_a = min(img_corners_mu-img_corners_a1,img_corners_mu-img_corners_a2);
  img_corners_b = min(img_corners_b1-img_corners_mu,img_corners_b2-img_corners_mu);
  img_corners_2 = min(img_corners_a,img_corners_b);
  
  % update corner map
  img_corners = max(img_corners,img_corners_1);
  img_corners = max(img_corners,img_corners_2);
end
findCorners::nonMaximumSuppression 非极大值抑制

原文给的非极大值抑制算法的详细原理参考:
http://www.cnblogs.com/liekkas0626/p/5219244.html
中第一个图片不知道是什么语言,我修改了一下,可以参考着看:
这里写图片描述
本文用了一个技巧,它先检测右上角部分,找到极大值点;
然后寻找该点的nn的区域(处于右边沿的按照实际大小检测相应的大小);
如果n
n区域中还有更大的点就跳出,跳出的点作为新的检测点,继续循环;如果没有则判断它是否大于tau,得到极大值点,然后循环。
直到检测完整张图片。

 function maxima = nonMaximumSuppression(img,n,tau,margin)%抑制范围0-n;极大值需要大于tau;

% extract parameters
width  = size(img,2);
height = size(img,1);

% init maxima list 初始化
maxima = [];

%% non maximum suppression 非极大抑制
for i=n+1+margin: n+1: width-n-margin
  for j=n+1+margin: n+1: height-n-margin
    maxi   = i;
    maxj   = j;
    maxval = img(j,i);

    for i2=i:i+n
      for j2=j:j+n
        currval = img(j2,i2);
        if currval>maxval
          maxi   = i2;
          maxj   = j2;
          maxval = currval;
        end
      end
    end
%%    
    failed = 0; 
    for i2=maxi-n:min(maxi+n,width-margin)
        for j2=maxj-n:min(maxj+n,height-margin)
        currval = img(j2,i2);
        if currval>maxval && (i2<i || i2>i+n || j2<j || j2>j+n)
          failed = 1;
          break;
        end
        end
      if failed
        break;
      end
    end
%%    
    if maxval>=tau && ~failed
      maxima = [maxima; maxi maxj];%将得到的极大值点放到maxima后面,初始的maxima为空
    end
    
  end
end
findCorners::refineCorners 亚像素化 没有看直接贴出来
%% subpixel refinement  亚像素
if refine_corners
  corners = refineCorners(img_du,img_dv,img_angle,img_weight,corners,10);
end

findCorners::去除杂点:1.不是边沿点;2.为角点打分,低于tau的删去

%% remove corners without edges
idx = corners.v1(:,1)==0 & corners.v1(:,2)==0;
corners.p(idx,:)  = [];
corners.v1(idx,:) = [];
corners.v2(idx,:) = [];

figure(4); imshow(uint8(I2));hold on;%%%%%%%%%%%%%%%%4
alpha=0:pi/20:2*pi;    %角度[0,2*pi] 
 R=4;                   %半径 
 x=R*cos(alpha); 
 y=R*sin(alpha); 
for i=1:size(corners.p,1)
 plot(x+corners.p(i,1),y+corners.p(i,2),'-') 
 fill(x+corners.p(i,1),y+corners.p(i,2),'r');
end

%%
disp('Scoring ...');
% score corners 角点得分
corners = scoreCorners(img,img_angle,img_weight,corners,radius);

% remove low scoring corners
idx = corners.score<tau;
corners.p(idx,:)     = [];
corners.v1(idx,:)    = [];
corners.v2(idx,:)    = [];
corners.score(idx) = [];

figure(5); imshow(uint8(I2));hold on;%%%%%%%%%%%%%%%%5
alpha=0:pi/20:2*pi;    %角度[0,2*pi] 
 R=4;                   %半径 
 x=R*cos(alpha); 
 y=R*sin(alpha); 
for i=1:size(corners.p,1)
 plot(x+corners.p(i,1),y+corners.p(i,2),'-') 
 fill(x+corners.p(i,1),y+corners.p(i,2),'r');
end
findCorners::最后,没看…还是写在这里

% make v1(:,1)+v1(:,2) positive (=> comparable to c++ code)
idx = corners.v1(:,1)+corners.v1(:,2)<0;
corners.v1(idx,:) = -corners.v1(idx,:);

% make all coordinate systems right-handed (reduces matching ambiguities from 8 to 4)
%使所有坐标系统向右(减少匹配模糊从8到4)
corners_n1 = [corners.v1(:,2) -corners.v1(:,1)];
flip       = -sign(corners_n1(:,1).*corners.v2(:,1)+corners_n1(:,2).*corners.v2(:,2));
corners.v2 = corners.v2.*(flip*ones(1,2));

% convert to 0-based index
corners.p = corners.p-1;
根据角点找边沿

chessboards = chessboardsFromCorners(corners);



  • 7
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值