角点检测与FindChessboardCorners函数

目的:

在研究坐标映射的相关问题时,遇到棋盘坐标匹配出错的问题。其中涉及到一个关键函数FindChessboardCorners以下将对其做一定的介绍和分析。

函数介绍:

FindChessboardCornersopencv一个函数,可以用来寻找棋盘图的内角点位置。


函数形式

int cvFindChessboardCorners( const void* image, CvSize pattern_size, CvPoint2D32f* corners, int* corner_count=NULL, int flags=CV_CALIB_CB_ADAPTIVE_THRESH );

参数说明

Image:

输入的棋盘图,必须是8位的灰度或者彩色图像。

pattern_size:

棋盘图中每行和每列角点的个数。

Corners:

检测到的角点

corner_count:

输出,角点的个数。如果不是NULL,函数将检测到的角点的个数存储于此变量。

Flags:

各种操作标志,可以是0或者下面值的组合:

CV_CALIB_CB_ADAPTIVE_THRESH -使用自适应阈值(通过平均图像亮度计算得到)将图像转换为黑白图,而不是一个固定的阈值。

CV_CALIB_CB_NORMALIZE_IMAGE -在利用固定阈值或者自适应的阈值进行二值化之前,先使用cvNormalizeHist来均衡化图像亮度。

CV_CALIB_CB_FILTER_QUADS -使用其他的准则(如轮廓面积,周长,方形形状)来去除在轮廓检测阶段检测到的错误方块。

补充说明

函数cvFindChessboardCorners试图确定输入图像是否是棋盘模式,并确定角点的位置。如果所有角点都被检测到且它们都被以一定顺序排布,函数返回非零值,否则在函数不能发现所有角点或者记录它们地情况下,函数返回0。例如一个正常地棋盘图右8x8个方块和7x7个内角点,内角点是黑色方块相互联通的位置。这个函数检测到地坐标只是一个大约的值,如果要精确地确定它们的位置,可以使用函数cvFindCornerSubPix

 

函数测试:

测试图像(左)和运行结果(右)


图像均为640*360的8*8黑白格棋盘图,7*7个内点。

  • 图1.计算机图像,成功检测出所有49个角点,顺序以行从左上到右下
  • 图2.正面实拍图像,检测出48个角点,其中正确47个,错误一个,没有标记顺序,只标记位置
  • 图3.正面实拍图像,成功检测出所有49个角点,顺序以行从左上到右下
  • 图4.侧面实拍图像,成功检测出所有49个角点,顺序以列从右上到坐下


结果分析:

  • 1图与3图,角特性良好,正面拍摄,函数顺利找到角点位置
  • 2图中,未检测出的右上角两个角点可能是由于胶带干扰,角特征变的不明显。检测到的错误点是因为背景图像中有黑色物体,导致计算机误认为其为黑色方格。
  • 4图中,由于拍摄角度倾斜,棋盘图像发生变形,角点查找顺序发生变化。可以通过重新排列矩阵Corners的大小来得到1图与3图同样的效果

反思与函数应用注意事项:

  • pattern_size参数传递内点数,8*8的棋盘只有7*7内点。
  • 图像选取应注意减少干扰,例如光照与背景等。
  • Corners中的角点坐标顺序排列规律不一定是以行从左上到右下。使用坐标计算映射关系时应提高警惕,对坐标进行重新排列。
基于VC++6.0的代码:
#include <iostream>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
using namespace std;
 
int main( )
{
    cout<<"Draw Chess OpenCV!"<<endl;  
    char* filename="..//image5.jpg";
	char* filename2="..//5.jpg";
    IplImage* imgRGB = cvLoadImage(filename); 
    IplImage* imgGrey = cvLoadImage(filename,CV_LOAD_IMAGE_GRAYSCALE); 
 
    if (imgGrey==NULL){//image validation
        cout<< "No valid image input."<<endl; 
        char c=getchar();
        return 1;
    } 
 
    //-------find chessboard corners--------------
    int corner_row=7;//interior number of row corners.(this can be countered by fingers.)
    int corner_col=7;//interior number of column corners.
    int corner_n=corner_row*corner_col;
    CvSize pattern_size=cvSize(corner_row,corner_col);
   // CvPoint2D32f* corners=new CvPoint2D32f[corner_n];
	CvPoint2D32f corners[49];
    int corner_count;
 
    int found=cvFindChessboardCorners(//returning non-zero means sucess.
        imgGrey,// 8-bit single channel greyscale image.
        pattern_size,//how many INTERIOR corners in each row and column of the chessboard.
        corners,//an array where the corner locations can be recorded.
        &corner_count,// optional, if non-NULL, its a point to an integer where the nuber of corners found can be recorded.
       // CV_CALIB_CB_ADAPTIVE_THRESH|CV_CALIB_CB_FILTER_QUADS// check page 382-383.
		0
        );
     cout<<"corner_count = "<<corner_count;
    //-------Draw the corner pattern-------
    cvDrawChessboardCorners(
        imgRGB,
        pattern_size,
        corners,
        corner_count,
        found
        );
	cvSaveImage(filename2,imgRGB);
    //to summary a bit of findings.
    cout<<"found="<<found<<endl;
    cout<<"x="<<corners[1].x;
    cout<<",y="<<corners[1].y<<endl;
	
    cvNamedWindow("Find and Draw ChessBoard", 0 );
    cvShowImage( "Find and Draw ChessBoard", imgRGB );
 
    cvWaitKey(0); 
 
    cvReleaseImage(&imgGrey);
    cvReleaseImage(&imgRGB);
    cvDestroyWindow("Find and Draw ChessBoard"); 
 
    return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值