OpenCV中文网站

 找回密码
 立即注册
搜索
热搜: 安装 配置
查看: 4543|回复: 3

C# 调用opencv的标定方法出现内存访问错误

[复制链接]
发表于 2014-5-16 01:19:40 | 显示全部楼层 |阅读模式
我用的不是Emgucv,我用的是cvlibcs那个dll。
代码是在百度上搜到的,原文是用C++写的,我在下面贴出地址,我给翻译成了C#,前辈可以直接看C#代码。
执行标定的时候cv.CvCalibrateCamera2(ref object_points0, ref image_points0, ref point_counts0, image_size, ref camera_matrix, ref distortion_coeffs, ref rotation_vectors, ref translation_vectors, 0);出错,accessviolationexception,尝试读取或写入受保护的内存。这通常指示其他内存已损坏
C# 代码
private unsafe void button1_Click(object sender, EventArgs e)
        {
            int n_board = 12;//图像数目
            int sn_board = 0;//成功找到角点的图像数目
            int board_w = 5;
            int board_h = 4;
            int board_n = board_h * board_w;//每幅图像的角点数
            CvSize patter_size = cxtypes.CvSize(board_w, board_h);//每幅图像的角点数
            CvPoint2D32f[] corners = new CvPoint2D32f[board_n];//一幅图像的角点数组
            CvMat object_points = cxcore.CvCreateMat(board_n * n_board, 3, cxtypes.CV_32FC1);
            CvMat image_points = cxcore.CvCreateMat(board_n * n_board, 2, cxtypes.CV_32FC1);
            CvMat point_counts = cxcore.CvCreateMat(n_board, 1, cxtypes.CV_32SC1);
            float* imagePointPtr = (float*)image_points.data;
            float* objectPointPtr = (float*)object_points.data;
            int* pointCountPtr = (int*)point_counts.data;
            CvSize image_size = cxtypes.CvSize(1600, 1200);
            GCHandle handleSrc1 = GCHandle.Alloc(corners, GCHandleType.Pinned);
            IntPtr connerPtr = handleSrc1.AddrOfPinnedObject();
            for (int i = 1; i <= n_board; i++)
            {
                string fileName = "image\\biaoding\\biaoding_" + (i).ToString() + ".bmp";
                /*读入图像*/
                IplImage SourceImg = highgui.CvLoadImage(fileName, highgui.CV_LOAD_IMAGE_COLOR);
                image_size = cxcore.CvGetSize(ref SourceImg);//图像的大小
                IplImage SourceImgGray = cxcore.CvCreateImage(image_size, (int)cxtypes.IPL_DEPTH_8U, 1);
                // 转成灰度图
                cv.CvCvtColor(ref SourceImg, ref SourceImgGray, cvtypes.CV_BGR2GRAY);
                int corner_count = 0;
                if (cv.CvFindChessboardCorners(ref SourceImgGray, patter_size, connerPtr, ref corner_count, cv.CV_CALIB_CB_ADAPTIVE_THRESH | cv.CV_CALIB_CB_FILTER_QUADS) == 0)
                {
                    cxcore.CvReleaseImage(ref SourceImgGray);
                    cxcore.CvReleaseImage(ref SourceImg);
                    Console.WriteLine("无法找出第" + i.ToString() + "幅图像的角点!");
                    return;
                }
                else
                {
                    cv.CvFindCornerSubPix(ref SourceImgGray, connerPtr, corner_count, cxtypes.CvSize(11, 11), cxtypes.CvSize(-1, -1), cxtypes.cvTermCriteria(cxtypes.CV_TERMCRIT_EPS + cxtypes.CV_TERMCRIT_ITER, 30, 0.1));//CvSize win 和matlab标定工具箱类似
                    cv.CvDrawChessboardCorners(ref SourceImg, patter_size, connerPtr, corner_count, 1);
                }
               for (int j = sn_board * board_n, k = 0; k < board_n; ++j, ++k)
                {
                    *(imagePointPtr + image_points.step / 4 * j + 0) = corners[k].x;
                    *(imagePointPtr + image_points.step / 4 * j + 1) = corners[k].y;
                    *(objectPointPtr + object_points.step / 4 * j + 0) = ((float)k) / board_w;
                    *(objectPointPtr + object_points.step / 4 * j + 1) = ((float)k) % board_w;
                    *(objectPointPtr + object_points.step / 4 * j + 2) = 0.0f;
                }
                *(pointCountPtr + point_counts.step / 4 * sn_board + 0) = board_n;
                sn_board++;
                cxcore.CvReleaseImage(ref SourceImgGray);
                cxcore.CvReleaseImage(ref SourceImg);
            }
            handleSrc1.Free();
            Console.WriteLine("一共成功获得" + sn_board.ToString() + "幅图的角点!无法获得" + (n_board - sn_board).ToString() + "幅图像的角点");
            //重新赋值
            CvMat object_points0 = cxcore.CvCreateMat(board_n * sn_board, 3, cxtypes.CV_32FC1);
            CvMat image_points0 = cxcore.CvCreateMat(board_n * sn_board, 2, cxtypes.CV_32FC1);
            CvMat point_counts0 = cxcore.CvCreateMat(sn_board, 1, cxtypes.CV_32SC1);
            float* imagePoint0Ptr = (float*)image_points0.data;
            float* objectPoint0Ptr = (float*)object_points0.data;
            for (int i = 0; i < sn_board * board_n; i++)
            {
                *(imagePoint0Ptr + image_points0.step / 4 * i + 0) = *(imagePointPtr + image_points.step / 4 * i + 0);
                *(imagePoint0Ptr + image_points0.step / 4 * i + 1) = *(imagePointPtr + image_points.step / 4 * i + 1);
                *(objectPoint0Ptr + object_points0.step / 4 * i + 0) = *(objectPointPtr + object_points.step / 4 * i + 0);
                *(objectPoint0Ptr + object_points0.step / 4 * i + 1) = *(objectPointPtr + object_points.step / 4 * i + 1);
                *(objectPoint0Ptr + object_points0.step / 4 * i + 2) = 0.0f;
            }
            int* pointCount0Ptr = (int*)point_counts0.data;
            for (int i = 0; i < sn_board; i++)
            {
                *(pointCount0Ptr + point_counts0.step / 4 * i + 0) = *(pointCountPtr + point_counts.step / 4 * i + 0);
            }
            cxcore.CvReleaseMat(ref object_points);
            cxcore.CvReleaseMat(ref point_counts);
            cxcore.CvReleaseMat(ref image_points);
            CvMat camera_matrix = cxcore.CvCreateMat(3, 3, cxtypes.CV_32FC1);
            CvMat distortion_coeffs = cxcore.CvCreateMat(1, 4, cxtypes.CV_32FC1);
             CvMat rotation_vectors = cxcore.CvCreateMat(sn_board, 3, cxtypes.CV_32FC1);
             CvMat translation_vectors = cxcore.CvCreateMat(sn_board, 3, cxtypes.CV_32FC1);
              /*摄像机标定并求得内部参数*/
            cv.CvCalibrateCamera2(ref object_points0, ref image_points0, ref point_counts0, image_size, ref camera_matrix, ref distortion_coeffs, ref rotation_vectors, ref translation_vectors, 0);
            cxcore.CvReleaseMat(ref object_points);
            cxcore.CvReleaseMat(ref point_counts);
            cxcore.CvReleaseMat(ref image_points);
            cxcore.CvReleaseMat(ref object_points0);
            cxcore.CvReleaseMat(ref point_counts0);
            cxcore.CvReleaseMat(ref image_points0);
            cxcore.CvReleaseMat(ref camera_matrix);
            cxcore.CvReleaseMat(ref distortion_coeffs);
            cxcore.CvReleaseMat(ref rotation_vectors);
            cxcore.CvReleaseMat(ref translation_vectors);
        }


C/C++ 代码
#include <cv.h>
#include <highgui.h>
#include <iostream>
using namespace std;
void PrintMat(CvMat*);
void FputMat(FILE *,CvMat *);
int main(int argc ,char * argv[])
{
/*读入图像*/
CvSize image_size;
int n_board=9;//图像数目
int sn_board=0;//成功找到角点的图像数目
int board_w=6;
int board_h=9;
int board_n=board_h*board_w;//每幅图像的角点数
CvSize patter_size=cvSize(board_w,board_h);//每幅图像的角点数
CvPoint2D32f * corners=new CvPoint2D32f[board_n];//一幅图像的角点数组
CvMat * object_points= cvCreateMat(board_n*n_board,3,CV_32FC1);
CvMat * image_points=cvCreateMat(board_n*n_board,2,CV_32FC1);
CvMat * point_counts=cvCreateMat(n_board,1,CV_32SC1);
for(int i=1;i<=n_board;i++)
{
  /*读入图像*/
  char path[100]="F:\\vs2008test\\mycalib_0\\right0";
  char num[10];
  itoa(i,num,10);
  strcat(num,".jpg");
  IplImage *SourceImg=cvLoadImage(strcat(path,num),CV_LOAD_IMAGE_COLOR);
  image_size=cvGetSize(SourceImg);//图像的大小
  IplImage *SourceImgGray=cvCreateImage(image_size,IPL_DEPTH_8U,1);
  cvCvtColor(SourceImg,SourceImgGray,CV_BGR2GRAY);
  cvNamedWindow("MyCalib",CV_WINDOW_AUTOSIZE);
  cvShowImage("MyCalib",SourceImg);
  cvWaitKey(NULL);
  /*提取角点精确到亚像素*/
  int corner_count;
  if(0==cvFindChessboardCorners(SourceImgGray,patter_size,corners,&corner_count,CV_CALIB_CB_ADAPTIVE_THRESH|CV_CALIB_CB_FILTER_QUADS))
  { cout<<"......无法找出第"<<i<<"幅图的角点"<<endl;
  cvWaitKey(NULL);
  cvReleaseImage(&SourceImgGray);
  cvReleaseImage(&SourceImg);
  continue;
  //return -1;
  }
  else
  {
   cvFindCornerSubPix(SourceImgGray,corners,corner_count,cvSize(11,11),cvSize(-1,-1),cvTermCriteria(
    CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,0.1));//CvSize win 和matlab标定工具箱类似
   cvDrawChessboardCorners(SourceImg,patter_size,corners,corner_count,1);
   cvShowImage("MyCalib",SourceImg);
   //cvSaveImage("F:\\vs2008test\\mycalib_0\\11.jpg",SourceImg);
  }
  cvWaitKey(0);
  for (int j=0;j<board_n;j++)
  {
   CV_MAT_ELEM(*image_points,float,sn_board*board_n+j,0)=corners[j].x;
   CV_MAT_ELEM(*image_points,float,sn_board*board_n+j,1)=corners[j].y;
   CV_MAT_ELEM(*object_points,float,sn_board*board_n+j,0)=float(j/board_w);
   CV_MAT_ELEM(*object_points,float,sn_board*board_n+j,1)=float(j%board_w);
   CV_MAT_ELEM(*object_points,float,sn_board*board_n+j,2)=0.0f;
   CV_MAT_ELEM(*point_counts,int,sn_board,0)=board_n;
  }
  sn_board++;
  cvReleaseImage(&SourceImgGray);
  cvReleaseImage(&SourceImg);
  cout<<"......成功找出第"<<i<<"幅图的角点"<<endl;
}
cout<<"......一共成功获得"<<sn_board<<"幅图像的角点"<<"......无法获得"<<n_board-sn_board<<"幅图像的角点"<<endl;
//重新赋值
CvMat * object_points0= cvCreateMat(board_n*sn_board,3,CV_32FC1);
CvMat * image_points0=cvCreateMat(board_n*sn_board,2,CV_32FC1);
CvMat * point_counts0=cvCreateMat(sn_board,1,CV_32SC1);
for (int i=0;i<sn_board*board_n;i++)
{
  CV_MAT_ELEM(*image_points0,float,i,0)=CV_MAT_ELEM(*image_points,float,i,0);
  CV_MAT_ELEM(*image_points0,float,i,1)=CV_MAT_ELEM(*image_points,float,i,1);
  CV_MAT_ELEM(*object_points0,float,i,0)=CV_MAT_ELEM(*object_points,float,i,0);
  CV_MAT_ELEM(*object_points0,float,i,1)=CV_MAT_ELEM(*object_points,float,i,1);
  CV_MAT_ELEM(*object_points0,float,i,2)=0.0f;
}
for (int i=0;i<sn_board;i++)
{
  CV_MAT_ELEM(*point_counts0,int,i,0)=CV_MAT_ELEM(*point_counts,int,i,0);
}
cvReleaseMat(&object_points);
cvReleaseMat(&point_counts);
cvReleaseMat(&image_points);
/*摄像机标定并求得内部参数*/
CvMat * camera_matrix=cvCreateMat(3,3,CV_32FC1);
CvMat * distortion_coeffs=cvCreateMat(1,4,CV_32FC1);
CvMat * rotation_vectors=cvCreateMat(sn_board,3,CV_32FC1);
CvMat * translation_vectors=cvCreateMat(sn_board,3,CV_32FC1);
int flags=0;

cvCalibrateCamera2(object_points0,image_points0,point_counts0,image_size,camera_matrix
  //,distortion_coeffs,NULL,NULL,flags);
  ,distortion_coeffs,rotation_vectors,translation_vectors,0);
}
C#和C/C++代码有出入,是因为C#我调试过,改成和《学习opencv》里一样的了,这个不影响。
打印矩阵的部分我就省略了,因为问题就出在标定这,请各位前辈指教一下。谢谢


回复

使用道具 举报

 楼主| 发表于 2014-5-16 22:36:19 | 显示全部楼层
问题解决了。足足两天纠结了两天之间。
我电脑安装了matlab,可能和我的C#opencv库有冲突,把matlab卸载了就好了。
回复 支持 反对

使用道具 举报

发表于 2014-7-22 08:54:20 | 显示全部楼层
学习了,正准备用这个。
回复 支持 反对

使用道具 举报

发表于 2015-5-20 21:09:14 | 显示全部楼层
你好,看到你的帖子,http://www.opencv.org.cn/forum.php?mod=viewthread&tid=31988,我现在正在做emgucv的相机标定,能实现opencv的,但是无法转成c#,看到你说的是用cvlibcs那个dll,但到处找过了没找到这个dll,特来请教,挺着急的,望回复!958933092@qq.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|OpenCV中文网站

GMT+8, 2024-4-16 13:04 , Processed in 0.010215 second(s), 16 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表