OpenCV 学习小结(错误排除、经验总结)

本文总结了在使用OpenCV过程中遇到的问题及其解决方案,包括找不到tbb_debug.dll的解决方法,VS2010加载包失败的修复,OpenCV中像素、信道的理解,cvGetCaptureProperty的正确使用,以及调试、数据格式、指针操作等常见问题的处理。
摘要由CSDN通过智能技术生成

如果你是用的为VS2010+OPENCV2.3.1,同时学习参考书为《学习OpenCV(中文版)》译者:于仕琪 刘瑞祯出版社:清华大学出版社,则代码不应参考书,而应使用下面链接(OpenCV中文网)http://www.opencv.org.cn/images/2/23/LearningOpenCV_Code.zip


具体看http://www.opencv.org.cn/index.php/%E9%A6%96%E9%A1%B5


**(1)没有找到 tbb_debug.dll


解决方法可以参考下面链接(OpenCV中文网)


http://www.opencv.org.cn/forum/viewtopic.php?p=52223


里面提到三种方法,都可能使用。我的PATH路径设置正确,所以只能用第二种或者第三种解决,我就是将\opencv\build\common\tbb\ia32目录下的tbb.dll复制改名为tbb_debug.dll(win7,vs2010,opencv2.3,运行程序,报错“计算机丢失tbb_debug.dll”)


**(2)VS2010未能正确加载包Visual Studio Class Designer Package


首先,按照提示用,应该用“devenv /log”命令查看生成的activitylog.xml报告。可以在cmd里切换到安装目录下的”……/Common7/IDE“下,然后运行"devenv /log",然后查看生成的activitylog.xml报告。应该看到类似红色标记的错误信息。


解决方法可以使:


方法一:重新正常启动电脑,运行VS,检查是否成功(一般都是因为系统未能及时加载UI控件包)


方法二:在cmd里切换到安装目录下的”……/Common7/IDE“下,然后运行"devenv /resetsettings“(重置),重新启动电脑和VS,检查是否成功


方法三:使用VS安装包内的修复或者卸载重装


**(3)OpenCV 中像素与信道


IplImage* cvCreateImage( CvSize size, int depth, int channels );


功能:创建图像头并分配数据      
参数说明:   
1) size 图像宽、高.   
2) depth 图像元素的位深度,可以是下面的其中之一:   
IPL_DEPTH_8U - 无符号8位整型   
IPL_DEPTH_8S - 有符号8位整型   
IPL_DEPTH_16U - 无符号16位整型   
IPL_DEPTH_16S - 有符号16位整型   
IPL_DEPTH_32S - 有符号32位整型   
IPL_DEPTH_32F - 单精度浮点数   
IPL_DEPTH_64F - 双精度浮点数  
3)channels:   
每个元素(像素)通道.可以是 1, 2, 3 或 4。通道是交叉存取的, 例如通常的彩色图像数据排列是:b0 g0 r0 b1 g1 r1 ... 这个函数也只能创建交叉存取图像.


所谓像素值,即对应像素的数值


所谓的通道,即表示该像素的数值个数


具体可参考下面:


1-灰度图——像素值是该像素点的亮度值


2-二值图,例如RGB565(RGB分别为5位,6位,5位,共16位,两个字节)


3-彩色图像,例如RGB(3通道,RGB,各8位,代表对应三基色色彩值)


4-彩色图像,例如RGBA(前三位同RGB,第四位代表透明度)


**(4)cvGetCaptureProperty函数使用


有时候这个函数单独使用并不能得到正确值,应该先调用一次cvQueryFrame后,再调用cvGetCaptureProperty才会返回正确的数值。这是一个bug,故建议在调用此函数前先调用cvQueryFrame。


**(5)CV_GAUSSIAN_5x5


应注意5乘以5是5x5,而不是5*5,中间为字母xyz中的x


**(6)Debug下点击“调试”或者“开始执行”不能显示图片


解决方法可参考:


http://www.opencv.org.cn/forum/viewtopic.php?p=56721


注意一定要使用绝对路径,且路径里“\”要用“\\”,比如:IplImage* img = cvLoadImage( "D:\\Lena.jpg" );


**(7)结构体与类


我们应发现,OpenCV中,所有的复杂数据结构都是用结构体的形式实现,并且以结构体指针的形式传递。因而OpenCV中没有私有数据!


例如:IplImage* out = cvCreateImage( cvGetSize( in ),in->depth, 1);


其中:返回值为图像类型(结构体)的指针;


cvGetSize的参数也为图像类型(结构体)的指针


利用指针传递数据,是OpenCV的特点,因而我们自己写函数时,返回与参数也应用指针或者数组或者&。


其中:const char*=“字符串”。故而


1)int main( int argc, char** argv ){


IplImage* img_rgb = cvLoadImage( argv[1] );


……
}


并cmd中调用“程序名.exe 参数”(参数1为程序名,参数2、3……为实际参数)


2)int main( ){


IplImage* img_rgb = cvLoadImage("me.jpg") ;


……


}


上面两者功能相同。


**(8)基本数据格式


1)


uchar* ptr;//无符号8位字符型
short* s;//16位短整数
int* i;//32位整数
float* fl;//32位单精度浮点数
double* db;//64位双精度浮点数


2)


type类型:CV_<bit_depth>(S|U|F)C<number_of_chanels>
例如:CV_32FC1,CV_8UC3
N维数组的M维点,存储的方式多种多样,但是最关键的一点,给定点的位置可以由下列公式计算得:
P=(row)*Ncols*Nchannels+(col)*Nchannels+(channel)=前行总个数+本行前总个数+本位置偏移
比如:3*3矩阵,存放CV_32FC3.则有:
x0 y0 z0|x1 y1 z1|x2 y2 z2
x3 y3 z3|x4 y4 z4|x5 y5 z5
x6 y6 z6|x7 y7 z7|x8 y8 z8
则y4在内存中的位置为:
p(y4)=(1)*3*3+(1)*3+(2)=14


3)IplImage中存储RGB,存储顺序为B-G-R


4)cvScalar有四个分量,但是可根据实际选择1,2,3,4,不用的将初始化为0,常见为1(标量),2(向量),3(RGB),4(RGBA),其中,具体代表的意思根据具体情况,比如IplImage中channels顺序为B-R-G,则cvScalar的顺序也就是代表为B-R-G,第四位为0;


**(9)指针与地址


区别参考本程序:


#include <stdio.h>
#include "cv.h"
#include "highgui.h"
void init_0( CvMat* mat ) {
float s = 0.0f;
for( int row=0; row<mat->height; row++ ) {
float* ptr = mat->data.fl + row * mat->step/4;
for( int col=0; col<mat->width; col++ ) {
//*ptr=0;/**ptr表示指针指向的内容,而ptr为指针本身(地址),printf("%d\t",*ptr);输出指针指向的内容,printf("%d\t",ptr);输出指针地址=&(*ptr)*/
//ptr=0;/*指针指向空,等于ptr=NULL,ptr为指针本身(地址);*/
*ptr=0;
printf("%d %d %d\t",ptr,&(*ptr),&ptr);/*由第三个输出可以看出,内存中开辟出一个内存单元,存储指针ptr,故而,&ptr不变,只是其指向(ptr中地址内容)变化而已,%x十六进制格式输出符%o八进制格式输出符%d十进制格式输出符%f浮点型输出符*/
ptr++;


}
printf("\n");
}
};
float sum( CvMat* mat ) {
float s = 0.0f;
for( int row=0; row<mat->height; row++ ) {
float* ptr = mat->data.fl + row * mat->step/4;
for( int col=0; col<mat->width; col++ ) {
s += *ptr++;/* 等于s+=*ptr;ptr++;*/
printf("%f\t",*ptr);


}
printf("\n");
}
return( s );
};


int main(int argc, char** argv)
{
CvMat *mat = cvCreateMat(5,5,CV_32FC1);
init_0(mat);
float element_3_2 = 7.7;
*((float*)CV_MAT_ELEM_PTR( *mat, 3,2) ) = element_3_2;
cvSetReal2D(mat,3,3,0.5000);
float s = sum(mat);
printf("%f\n",s);
return 0;
}


**(10)函数多参数传递原理


首先说一下,windows中,堆栈是从高地址开始压栈的。其次,函数参数是以栈的形式存取的,自右向左压入堆栈。具体可参考下面程序:


#include <iostream>//支持system()
using namespace std;//必须加,支持cout,endl



void fun(int a, ...)
{
int *temp =
&a;
temp++;
for (int i = 0; i < a; ++i)
{
cout << *temp
<< endl;
temp++;
}
}



int main()
{
int a = 1;
int b = 2;
int c = 3;
int d =
4;
fun(4, a, b, c, d);
system("pause");
return
0;
}
输出:
1
2
3
4


省略多参数函数书写规则可参考下面链接:


http://www.cnblogs.com/rainduck/archive/2010/11/10/1873417.html


**(11)非MFC下调试窗口输出函数


随便建一个.H头文件,把下面函数放进去即可


/*我写在dbgprintf.h*/


#include <stdio.h>
#include <stdarg.h>
#include <ctype.h> #define DBG_NUM 4067 void __cdecl DbgPrintf(const char *, ...);//声明,利于编译
void __cdecl dbgprintf(const char *format, ...)
{ char buf[DBG_NUM]; char *bufp = buf;
va_list args;
va_start(args, format); bufp += _vsnprintf(bufp, sizeof buf - 1, format, args);//指针P移动到下一个要写入的部分或者结尾处,应保证最后一个位置必须写‘\0’,故而只写sizeof buf -1
va_end(args); if (bufp<buf)
{
bufp+=DBG_NUM;//越界检查,重新定位,最后一个位置上
OutputDebugStringA("the buff is not enough\n");
} *bufp='\0';
OutputDebugStringA(buf); OutputDebugStringA("\n");//应明白,OutputDebugString(const char *),即参数为静态数组
}


**(12)字符串(组)类型转换


1)char [],const char[],string


string add_to = "hello!";


const char *cfirst = add_to.c_str();


char *copy = new char[strlen(cfirst) + 1];


strcpy(copy, cfirst);


add_to = copy;


delete [] copy;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值