文章目录
一、GDB调试练习
让我们编写一个程序test2.c来进行GDB调试练习
test2.c的源码如下:
#include <stdio.h>
void shownum(int x)
{
while (x > 10)
{
printf("%d", x % 10);
x = x / 10;
}
printf("%d\n", x);
}
int main(void)
{
int x;
printf("enter a number :");
scanf("%d", &x);
printf("result: ");
shownum(x);
}
该程序的作用是输入一个数,输出他的倒置,比如输入100,应该输出001。但仔细阅读该程序发现该程序是错误的,输入100,输出的结果却是010。如下图:
为了解决这个问题,找到错误所在,我们对该程序进行调试。
步骤一:编译
输入命令行:
gcc -o test2 -g test2.c
步骤二:调试
输入命令行:
gdb test2
步骤三:进行调试
-
输入l ,显示代码了内容
-
设置断点
b 16 4 9
-
查看断点信息
-
run
-
查看变量x的值,x为刚刚输入的100
-
continue并继续查看变量x的值
此时程序运行至断点2,此时x的值为100
-
进行continue并继续查看变量x的值
此时程序运行到断点3,此时x的值为10
-
进行continue
发现此时程序已经结束了,结果也输出错误了,result的后两位即是上一步变量x的值,说明程序并没有进入二次循环,本该再次循环才能输出正确结果的,说明该程序的错误是出在循环条件上。
步骤4:解决问题
将循环条件改为(x>=10)再次运行此程序发现问题已解决:
这样,就通过调试的方法找到了程序的错误。
二、opencv图像库
1、安装opencv3.4.1
参考学姐博客:https://cungudafa.blog.csdn.net/article/details/84451066
2、编写打开图片进行特效显示的代码
在安装好OpenCV后进行以下步骤:
步骤一:创建工作目录与文件
在opencv-3.4.1下新建文件夹test,进入该目录后,创建工作文件test.cpp
步骤二:在test.cpp中编写源码
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
CvPoint center;
double scale = -3;
IplImage* image = cvLoadImage("lena.jpeg");
argc == 2? cvLoadImage(argv[1]) : 0;
cvShowImage("Image", image);
if (!image) return -1; center = cvPoint(image->width / 2, image->height / 2);
for (int i = 0;i<image->height;i++)
for (int j = 0;j<image->width;j++) {
double dx = (double)(j - center.x) / center.x;
double dy = (double)(i - center.y) / center.y;
double weight = exp((dx*dx + dy*dy)*scale);
uchar* ptr = &CV_IMAGE_ELEM(image, uchar, i, j * 3);
ptr[0] = cvRound(ptr[0] * weight);
ptr[1] = cvRound(ptr[1] * weight);
ptr[2] = cvRound(ptr[2] * weight);
}
Mat src;Mat dst;
src = cvarrToMat(image);
cv::imwrite("test.jpeg", src);
cvNamedWindow("test",1); imshow("test", src);
cvWaitKey();
return 0;
}
步骤三:用g++进行编译
输入命令行
g++ test.cpp -o test `pkg-config --cflags --libs opencv`
使用pkg-config时,选项–cflags 它是用来指定程序在编译时所需要头文件所在的目录,选项 –libs则是指定程序在链接时所需要的动态链接库的目录。
步骤四:运行
输入命令行
./test
效果:
事先将要展示的图片放在mytest目录下
3、编写一个打开摄像头显示处理视频的程序代码
1)、打开摄像头
步骤一:创建工作目录与文件
在opencv-3.4.1下新建文件夹video,进入该目录后,创建工作文件videoopen.cpp
步骤二:在videoopen.cpp中编写源码
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
VideoCapture capture(0);
while(1)
{
Mat frame;
capture >> frame;
imshow(“读取视频帧”,frame);
waitKey(30);
}
system(“pause”);
return 0;
}
针对该源码,我们需要知道的是:
-
如果需要打开硬盘上一个视频文件来播放,第7行代码应该VideoCapture capture(“*.avi”);
-
Mat是一个类。由两部分数据组成:矩阵头(包括矩阵尺寸、存储方法、存储地址等信息)和一个指向所有像素值的矩阵(根据所选存储方法不同,矩阵可以是不同的维数)的指针。
-
waitKey延时越长 fps越小 出现跳帧 摄像头显示变卡,故要有一定的延时
-
加一个break代码,如if(ch == 27) break;
步骤二:用g++编译
输入命令行
g++ videoopen.cpp -o videoopen `pkg-config --cflags --libs opencv`
发现已经产生videoopen执行文件
步骤三:运行
输入命令行
./videoopen
效果:
2)、打开摄像头采集图像并保存
步骤一:创建工作目录与文件
在opencv-3.4.1下新建文件夹last,进入该目录后,创建工作文件last.cpp
步骤二:在last.cpp中编写源码
#include<iostream>
#include <opencv2/opencv.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
void main()
{
//打开电脑摄像头
VideoCapture cap(0);
if (!cap.isOpened())
{
cout << "error" << endl;
waitKey(0);
return;
}
//获得cap的分辨率
int w = static_cast<int>(cap.get(CV_CAP_PROP_FRAME_WIDTH));
int h = static_cast<int>(cap.get(CV_CAP_PROP_FRAME_HEIGHT));
Size videoSize(w, h);
VideoWriter writer("RecordVideo.avi", CV_FOURCC('M', 'J', 'P', 'G'), 25, videoSize);
Mat frame;
int key;//记录键盘按键
char startOrStop = 1;//0 开始录制视频; 1 结束录制视频
char flag = 0;//正在录制标志 0-不在录制; 1-正在录制
while (1)
{
cap >> frame;
key = waitKey(100);
if (key == 32)//按下空格开始录制、暂停录制 可以来回切换
{
startOrStop = 1 - startOrStop;
if (startOrStop == 0)
{
flag = 1;
}
}
if (key == 27)//按下ESC退出整个程序,保存视频文件到磁盘
{
break;
}
if (startOrStop == 0 && flag==1)
{
writer << frame;
cout << "recording" << endl;
}
else if (startOrStop == 1)
{
flag = 0;
cout << "end recording" << endl;
}
imshow("picture", frame);
}
cap.release();
writer.release();
destroyAllWindows();
}
步骤二:用g++编译
输入命令行
g++ last.cpp -o last `pkg-config --cflags --libs opencv`
发现已经产生last可执行文件
步骤三:运行
输入命令行
./last
视频录制完后查看查看工作目录下是否有录制完成的视频:
效果: