C,C++用过的调试方式/函数/小程序

这篇博客详细介绍了C++中的一些调试方法,包括注释和取消注释的快捷方式,以及OpenCV中用于图像处理的重要函数,如`addWeighted`、`copyTo`和`createTrackbar`等。`addWeighted`用于加权合并两个数组,`copyTo`用于复制和转换矩阵,`createTrackbar`则用于创建交互式的滑动条。此外,还提到了`destroyAllWindows()`、`destroyWindow()`、`drawContours`等函数以及如何使用`imshow`显示图像。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

调试方式

1)注释:组合键“Ctrl+K+C”;
2)取消注释:组合键“Ctrl+K+U”

函数

addWeighted
原型: void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1);
第一个参数,InputArray类型的src1,表示需要加权的第一个数组,常常填一个Mat。
第二个参数,alpha,表示第一个数组的权重(0-1.0)
第三个参数,src2,表示第二个数组,它需要和第一个数组拥有相同的尺寸和通道数。
第四个参数,beta,表示第二个数组的权重值(0-1.0)。
第五个参数,dst,输出的数组,它和输入的两个数组拥有相同的尺寸和通道数。
第六个参数,gamma,一个加到权重总和上的标量值。看下面的式子自然会理解(通常设置为0)。
第七个参数,dtype,输出阵列的可选深度,有默认值-1。;当两个输入数组具有相同的深度时,这个参数设置为-1(默认值),即等同于src1.depth()。
如果用数学公式来表达,addWeighted函数计算如下两个数组(src1和src2)的加权和,得到结果输出给第四个参数。即addWeighted函数的作用可以被表示为为如下的矩阵表达式为:
dst = src1[I]*alpha+ src2[I]*beta + gamma;
copyTo
原型:void copyTo( OutputArray m, InputArray mask ) const;
createTrackbar
C++: int createTrackbar(conststring& trackbarname, conststring& winname, int* value, int count, TrackbarCallback onChange=0,void* userdata=0);
创建一个具有特定名称和范围的轨迹条(Trackbar,或者说是滑块范围控制工具),指定一个和轨迹条位置同步的变量。而且要指定回调函数onChange(第五个参数),在轨迹条位置改变的时候来调用这个回调函数。并且我们知道,创建的轨迹条显示在指定的winname(第二个参数)所代表的窗口上。
第一个参数,const string&类型的trackbarname,表示轨迹条的名字,用来代表我们创建的轨迹条。
第二个参数,const string&类型的winname,填窗口的名字,表示这个轨迹条会依附到哪个窗口上,即对应namedWindow()创建窗口时填的某一个窗口名。
第三个参数,int* 类型的value,一个指向整型的指针,表示滑块的位置。并且在创建时,滑块的初始位置就是该变量当前的值。
第四个参数,int类型的count,表示滑块可以达到的最大位置的值。PS:滑块最小的位置的值始终为0。
第五个参数,TrackbarCallback类型的onChange,首先注意他有默认值0。这是一个指向回调函数的指针,每次滑块位置改变时,这个函数都会进行回调。并且这个函数的原型必须为void XXXX(int,void*);其中第一个参数是轨迹条的位置,第二个参数是用户数据(看下面的第六个参数)。如果回调是NULL指针,表示没有回调函数的调用,仅第三个参数value有变化。
第六个参数,void*类型的userdata,他也有默认值0。这个参数是用户传给回调函数的数据,用来处理轨迹条事件。如果使用的第三个参数value实参是全局变量的话,完全可以不去管这个userdata参数。

destroyAllWindows()
destroyWindow()
drawContours

 void drawContours( InputOutputArray image, InputArrayOfArrays contours,int contourIdx, const Scalar& color,int thickness=1, int lineType=8,InputArray hierarchy=noArray(),int maxLevel=INT_MAX, Point offset=Point() );

用来将轮廓绘制出来
image:表示目标图像;
contours:表示输入的轮廓组,每一组轮廓由点vector构成;
contourIdx:指明画第几个轮廓,如果该参数为负值,则画全部轮廓;
color:为轮廓的颜色;
thickness:为轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部;
lineType:为线型;
第七个参数为轮廓结构信息
第八个参数为maxLevel
empty
inline bool Mat::empty() const { return data == 0 || total() == 0; }
判断当前的mat对象是否为空;

img = imread(FILE_PATH_TEST, 0);//Read the gray image  

if(img.empty())
{
 cout << "Could not read input image file: " << inputImage << endl;
        return -1;
}

fclose

int fclose( FILE *fp );

fclose是一个函数名,功能是关闭一个流。注意:使用fclose()函数就可以把缓冲区内最后剩余的数据输出到内核缓冲区,并释放文件指针和有关的缓冲区。

findContours

void findContours( InputOutputArray image, OutputArrayOfArrays contours,OutputArray hierarchy, int mode,int method, Point offset=Point());

retrieves contours and the hierarchical information from black-n-white image
image:输入图像image必须为一个2值单通道图像;
contours:检测的轮廓数组,每一个轮廓用一个point类型的vector表示
hiararchy:和轮廓个数相同,每个轮廓contours[i]对应4个hierarchy元素hierarchy[ i ][ 0 ] ~hierarchy[ i ][ 3 ],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,该值设置为负数。
mode:表示轮廓的检索模式
CV_RETR_EXTERNAL表示只检测外轮廓
CV_RETR_LIST检测的轮廓不建立等级关系
CV_RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
CV_RETR_TREE建立一个等级树结构的轮廓。
method:为轮廓的近似办法
CV_CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
CV_CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
offset:表示代表轮廓点的偏移量,可以设置为任意值。对ROI图像中找出的轮廓,并要在整个图像中进行分析时,这个参数还是很有用的。
fopen

FILE * fopen(const char * path,const char * mode)

文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败则返回NULL,并把错误代码存在errno中;

#include<stdio.h>

#define F_PATH "d:\\myfile\\file.dat"
int main(void)
{
    FILE*fp=NULL;//需要注意
    fp=fopen(F_PATH,"r");
    if(NULL==fp)
    {
        return -1;//要返回错误代码
    }
    fclose(fp);
    fp=NULL;//需要指向空,否则会指向原打开文件地址

     return 0;
}

fscanf

int fscanf(FILE*stream,constchar*format,[argument...]);

根据数据格式(format)从输入流(stream)中写入数据(argument)

#include <stdlib.h>
#include <stdio.h>
int main(void)
{
    int i;
    printf("Input an integer:");
    /*从标准输入中读取一个整数*/
    if(fscanf(stdin, "%d",&i))
    printf("The integer read was:%d\n", &i);
    else
    {
        fprintf(stderr, "Error reading an integer from stdin.\n");
        exit(1);
    }
    return 0;
}
返回EOF如果读取到文件结尾。

imread
原型:Mat imread(const string& filename, intflags=1 );
第一个参数,const string&类型的filename,填我们需要载入的图片路径名
在Windows操作系统下,OpenCV的imread函数支持如下类型的图像载入:
1.Windows位图 - .bmp, .dib
2.JPEG文件 - .jpeg, .jpg, *.jpe
3.JPEG 2000文件- *.jp2
4. PNG图片 - *.png
5. 便携文件格式- .pbm, .pgm, *.ppm
6. Sun rasters光栅文件 - .sr, .ras
7.TIFF 文件 - .tiff, .tif
第二个参数,int类型的flags,为载入标识,它指定一个加载图像的颜色类型。可以看到它自带缺省值1.所以有时候这个参数在调用时我们可以忽略,在看了下面的讲解之后,我们就会发现,如果在调用时忽略这个参数,就表示载入三通道的彩色图像,0表示将读入的图像转换成灰度图像。
imshow
原型:void imshow(const string& winname, InputArray mat);
第一个参数,const string&类型的winname,填需要显示的窗口标识名称。
第二个参数,InputArray 类型的mat,填需要显示的图像。
imwrite
原型:bool imwrite(const string& filename,InputArray img, const vector& params=vector() );
第一个参数,const string&类型的filename,填需要写入的文件名就行了,带上后缀,比如,“123.jpg”这样。
第二个参数,InputArray类型的img,一般填一个Mat类型的图像数据就行了。
第三个参数,const vector&类型的params,表示为特定格式保存的参数编码,它有默认值vector(),所以一般情况下不需要填写。
malloc

extern void *malloc(unsigned int num_bytes);;

malloc 向系统申请分配指定size个字节的内存空间,void* 表示未确定类型的指针。C,C++规定,void* 类型可以通过类型转换强制转换为任何其它类型的指针

merge
原型:void merge(const Mat* mv, size_tcount, OutputArray dst)
merge()函数的功能是split()函数的逆向操作,将多个数组组合合并成一个多通道的数组
第一个参数,mv,填需要被合并的输入矩阵或vector容器的阵列,这个mv参数中所有的矩阵必须有着一样的尺寸和深度。
第二个参数,count,当mv为一个空白的C数组时,代表输入矩阵的个数,这个参数显然必须大于1.
第三个参数,dst,即输出矩阵,和mv[0]拥有一样的尺寸和深度,并且通道的数量是矩阵阵列中的通道的总数
namedWindow
原型:void namedWindow( const string& winname, int flags=WINDOW_AUTOSIZE );
第一个参数,const string&型的name,即填被用作窗口的标识符的窗口名称。
第二个参数,int 类型的flags ,窗口的标识,可以填如下的值:
WINDOW_NORMAL设置了这个值,用户便可以改变窗口的大小(没有限制);
WINDOW_AUTOSIZE如果设置了这个值,窗口大小会自动调整以适应所显示的图像,并且不能手动改变窗口大小(默认);
WINDOW_OPENGL 如果设置了这个值的话,窗口创建的时候便会支持OpenGL
namedWindow函数的作用是,通过指定的名字,创建一个可以作为图像和进度条的容器窗口。如果具有相同名称的窗口已经存在,则函数不做任何事情;
rand

int rand(void);

返回一个[0,RAND_MAX]间的随机整数。
Rect
原型:template inline Rect_<Tp>::Rect() : x(0), y(0), width(0), height(0) {}
指定矩形的左上角坐标(构造函数的前两个参数)和矩形的长宽(构造函数的后两个参数)就可以定义一个矩形区域
举例:
Mat imageROI= srcImage1(Rect(100,100,logoImage.cols,logoImage.rows));
获取图像srcImage1的起始位置为100,100,width=logoImage.cols,height=logoImage.rows区域的图像;
size
得到Mat类型img的size,可以使用函数img.size(),注意这里有括号。但是在需得到img的行和列时,不需要使用括号,即使用img.rows和img.cols.
sizeof
是C/C++中的一个操作符(operator),简单的说其作用就是返回一个对象或者类型所占的内存字节数。如在C语言中使用sizeof(char),其结果为1,表示char类型占1个字节(8比特)
split
原型:void split(InputArray m,OutputArrayOfArrays mv);
第一个参数,InputArray类型的m或者const Mat&类型的src,填我们需要进行分离的多通道数组。
第二个参数,OutputArrayOfArrays类型的mv,填函数的输出数组或者输出的vector容器。
waitKey
原型:int waitKey(int delay=0);
zeros

static MatExpr zeros(Size size, int type);//Matlab-style matrix initialization

初始化图像对象为0,如:

Mat dst = Mat::zeros(img.size(), CV_8UC3);

//-----------------------------------【命名空间声明部分】---------------------------------------  
//     描述:包含程序所使用的命名空间  
//-----------------------------------------------------------------------------------------------    
#include<opencv2/core/core.hpp>  
#include<opencv2/highgui/highgui.hpp>  
#include <cv.h>  
#include <highgui.h>  
#include <iostream>   
using namespace cv;  
using namespace std;  


#define   FILE_PATH_IMAGE1  "E:\\sunwork\\OpenCVTest\\TestImage\\fhd1.jpg"
#define   FILE_PATH_IMAGE2  "E:\\sunwork\\OpenCVTest\\TestImage\\logo.jpg"
#define   FILE_PATH_IMAGE3  "E:\\sunwork\\OpenCVTest\\TestImage\\fhd2.jpg" 
#define   FILE_PATH_TEST  "E:\\sunwork\\OpenCVTest\\TestImage\\TEST.jpg" 

//-----------------------------------【全局函数声明部分】--------------------------------------  
//     描述:全局函数声明  
//-----------------------------------------------------------------------------------------------  
bool MultiChannelBlending();  

//-----------------------------------【main( )函数】--------------------------------------------  
//     描述:控制台应用程序的入口函数,我们的程序从这里开始  
//-----------------------------------------------------------------------------------------------  
int main(  )  
{  

       if(MultiChannelBlending())  
       {  
              cout<<endl<<"OK";  
       }  

       waitKey(0);  
       return 0;  
}  


//-----------------------------MultiChannelBlending( )--------------------------------  
//     Description:
//-----------------------------------------------------------------------------------------------  
bool MultiChannelBlending()  
{  
       //【0】定义相关变量  
       Mat srcImage;  
       Mat logoImage;  
       vector<Mat>channels;  
       Mat  imageBlueChannel;  


       logoImage=imread(FILE_PATH_IMAGE2,0);  
       srcImage=imread(FILE_PATH_TEST);  

       if(!logoImage.data ){ printf("Read image wrong\n"); return false; }  
       if(!srcImage.data ) { printf("Read image wrong\n"); return false; }  

       split(srcImage,channels);

       imageBlueChannel=channels.at(0);//0:Blue  

       addWeighted(imageBlueChannel(Rect(100,100,logoImage.cols,logoImage.rows)),1.0,  
              logoImage,0.5,0,imageBlueChannel(Rect(100,100,logoImage.cols,logoImage.rows)));  


       merge(channels,srcImage);//channels.at(0) have been converted  

       namedWindow("WindowName");  
       imshow("WindowName",srcImage);  

       return true;  
}  

1、打印测试数据到txt中

FILE *ycocg2rgbOutputData;
ycocg2rgbOutputData=fopen("ycocg2rgbOutputData.txt", "wt");
for(i=0;i<HEIGHT;i++)
{
     for(j=0;j<WIDTH;j++)
    {
       if (j==WIDTH)
        {
            fprintf(ycocg2rgbOutputData, "\n");//printf new line
        }
         else
        {
        fprintf(ycocg2rgbOutputData, "%d,",op->data.rgb.r[i][j]);//printf data to the new file
        }

    }
}
fclose(ycocg2rgbOutputData);

2、从txt或者csv等文件中读取数据到数组中
思想:使用指针fp指向文件的内容,依次读取文件的字符并拼接成字符串,遇到”,”则表示已经读取完当前内容,则将已经读取到字符串转换成整型或者浮点型放入存储单元中,如果遇到换行符则也对应将数据存放到存储单元新的一行中,做到对应。其中需要注意的是当检测到字符串拼接完成之后需要做清空动作。
这里假设csv数据是480*270,且每一个格子的数据长度不超过30。(将程序中的txt换成csv同样可行)

    FILE *fp = NULL;
    int numCount=0;
    int rows=0;
    int cols=0;
    int csvdata[480][270];
    char c;
    char s[30]={0};//csv grid data length is small than 30

    fp = fopen("example8bit.txt", "r"); //or csv
    if(fp == NULL)
    {
        printf("file can not be opened or is not correct\n");  
        exit(0);  

    }


    while((c=getc(fp))!=EOF)
    {
        if (c==','||c=='\n')
        {
            numCount=0;
            csvdata[rows][cols]=atoi(s);//convert the string to float
            cols++;
            memset(s,0x00,sizeof (char) * 30);//Reinitial the string
            if (c=='\n')
            {
                rows++;
                cols=0;
            }
            continue;
        }
        else
        {
            s[numCount]=c;
            numCount++;

        }
    }

    fclose(fp);
    fp=NULL;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值