这周开始学习ubuntu上的用opencv库编写图像视频程序以及顺便进行gdb调试。^ ^安装opencv都牵出了一些问题,嵌入式学习道阻且长,以下是本周的学习记录
文章目录
前言
应用程序的调试是开发过程中必不可少的环节之一。Linux下的GNU的调试器称为GDB。GDB提供的功能是什么?如何进行GDB调试?这是我们应该学习的。
目前计算机视觉超火,但如今关于这方面计算机软件良莠不齐,opencv致力于真实世界的实时应用,通过优化的C代码的编写对其执行速度带来了可观的提升opencv的应用市场也出现了。学嵌入式肯定要玩玩opencv😏
一、调试器GDB
1.GDB调试器介绍
GDB最早时候一个叫Richard Stallman的人编写的,它被创造出来是用来调试C和C++程序。使用者能在程序运行是观察程序内部结构和内存的使用情况。GDB是一种基于命令行工作模式下的程序,工作在字符模式,由多个不同的图形用户界面前端予以支持,每个前端都能以多种方式提供调试控制功能。特别适合修复程序代码里的问题。
其官方网站 : link
以下是GDB所提供的一些功能:
1.启动程序,而且可以设置运行环境和参数来运行指定程序。
2.让程序在指定断电处停止执行。
3.对程序作出相应的调整,让我们能一个一个纠正错误后继续调试。
注意:GDB调试的是可执行文件,而不是源程序
如果我们想让GDB调试编译后生成的可执行文件,在使用GDB工具调试程序之前,必须使用带有-g或-gbd编译选项的GCC命令来编译源程序!
列如:
# gcc -g -o test test.c
2.GDB命令
1.GDB命令语法:
GDB命令如下:
# gdb [参数] Filename
2.GDB命令里常用的参数:
-help:列出所有参数
-symbols=file
-s file:读出文件的所有符号
-core
-c:这里的core是程序非法执行后core dump产生的文件
-directory
-d:加入一个源文件的搜索路径。默认搜索路径是环境变量中PATH所定义的路径
-quiet
-q:使用该选项不像是GDB的介绍和版权信息
3.GDB调试命令
命令 | 功能 |
---|---|
file | 装入想要调试的可执行文件 |
kill | 终止正在调试的程序 |
list | 列出产生执行文件的源代码的一部分,查看源码 |
next | 执行一行源代码但不进入函数内部 |
step | 执行一行源代码而且进入函数内部 |
run | 执行当前被调试的程序 |
c | 继续运行程序 |
quit | 终止gdb |
watch | 使你能监视一个变量的值而不管它何时被改变。backtrace栈跟踪,查出代码被谁调用 |
查看变量的值 | |
make | 使你能不退出gdb就可以重新产生可执行文件 |
shell | 使你能不离开gdb就执行UNIX shell命令 |
whatis | 显示变量或函数类型 |
break | 在代码里设断点,这将使程序执行到这里时被挂起 |
info break | 显示当前断点清单,包括到达断点处的次数等 |
info files | 显示被调试文件的详细信息 |
info func | 显示所有的函数名称 |
info local | 显示当函数中的局部变量信息 |
info prog | 显示被调试程序的执行状态 |
delete n | 删除第n个断点 |
disable n | 关闭第n个断点 |
enable n | 开启第n个断点 |
ptype | 显示结构定义 |
set variable | 设置变量的值 |
call name args | 调用并执行名为name,参数为args的函数 |
Finish | 终止当前函数并输出返回值 |
return value | 停止当前函数并返回value给调用者 |
二、GDB调试案列
现在你关于GDB我们已经有一定了解,现在开始在Ubuntu系统上练习一下程序代码的GDB调试吧。^ ^
1.案列代码
现在我们看到如下代码,这个代码实现对一个整型数的反转功能,比如输入12345,输出54321。但问题来了,我们输入100时,程序的输出结果却不正确,请找出问题
代码如下:
#include <stdio.h>
void ShowRevertNum(int iNum)
{
while (iNum > 10)
{
printf("%d", iNum % 10);
iNum = iNum / 10;
}
printf("%d\n", iNum);
}
int main(void)
{
int iNum;
printf("Please input a number :");
scanf("%d", &iNum);
printf("After revert : ");
ShowRevertNum(iNum);
}
2.启动GDB
1.首先我们创造一个.c文件(这里我创建的文件为yoyo.c)
使用命令:
gedit yoyo.c
2.弹出编译窗口将案列代码张贴上去
3.编译这个测试程序
使用命令:
gcc -o yoyo -g yoyo.c
4.最后
使用命令:
gdb yoyo
出现如下内容:
这说明我们可以进行GDB调试
3.查看源码
这里我们用到前面GDB调试命令里的知识,我们输入list来查看源代码。
注意这里查看源代码是默认显示10行,按回车键才能继续看余下的
一开始只有10行:
按回车键:
我们看出这个代码一共18行。
4.设置断点
这里运用了之前讲的break和info breakpoints命令的使用。举个例子。
输入 b 1:在第十行设置断点
如果你想查看断点信息
输入info b:查看断点信息
这样就显示了我们设置的断点的信息。
5.运行程序
这里要运用到我们之前才学到的run和continue
再写一遍:
run :运行程序直到遇到 结束或者遇到断点等待下一个命令;
continue:继续运行程序。遇到下一个断点停止运行;
因为我们只设置了一个断点,于是这样。我们加一个断点再来一次。
看出区别了。
6.查看变量
如何看变量?学习一下下面两个命令。
print :查看变量的值
whatis:显示变量或函数类型
这个意思是说iNum的数据类型是整形
7.GDB的段错误调试
1.首先创建文件,并且输入如下代码:
#include<stdio.h>
#include<string.h>
#define BUFSIZE 256
static char acBuf[BUFSIZE];
static char *pStr;
int main(void)
{
printf("please input a string: ");
gets(pStr);
printf("\nyour string is:%s\n",pStr);
}
2.开始调试
输入命令:gcc -o qq -g qq.c
出现了这个。段错误就看这个
3.GDB调试
输入:gdb qq
修改变量的值,输入:set variable pStr=&acBuf
就是将pStr这个变量用acBuf替换
4.生成core文件
创建方法和之前一样
调试我们使用的命令是:gcc -o file -g file.c
使用命令生成core文件: ulimit –c 1000
最后出现:
5.gdb配合core文件
输入命令:gdb file core
出现
以上,gdb调试训练结束
三.opencv图像编程
前期安装配置工作没截图。可以去官网下载再参看以下大神的文章: link.我是跟着她的做的opencv的安装和配置。
1.Linux下编程
首先在opencv-3.4.1下新建文件夹mytest
要在opencv-3.4.1上要使用如下命令:
cd opencv-3.4.1
创建:
mkdir mytest
创建test.cpp:
touch test.cpp
进入编程:
sudo gedit /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.png", src);
cvNamedWindow("test",1); imshow("test", src);
cvWaitKey();
return 0;
}
保存并且开始编译,使用命令如下:
g++ test.cpp -o test pkg-config --cflags --libs opencv
出现如下的file:
用命令运行test出现如下:
成功!
2.摄像头显示处理视频
1.创建teest1.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;
}
输入命令:
g++ teest1.cpp -o teest1 `pkg-config --cflags --libs opencv`^C
执行命令:
./teest1
记得开摄像头
以及设置
使用命令:cheese
(这里我强制退了使虚拟机remake重开了,没搞清原因)
正确的退出做法:输入:ctrl+c
麻了
3.处理视频
进行视频的处理了!
1.首先,先在当前目录下保存一个视频
2.点开全选进行一个10分钟的下载就能打开视频。
(:D把整部漫画唯一正常的几页录进去的一个视频)
3.思考题里,这里我们改第七行的代码
VideoCapture capture("gudu.mp4");
再来运行!
(当时是以怎样的心情录这玩意的XD)
至此,完成本次实验。
4.小结
通过本次作业的练习,了解了虚拟机条件下的程序调试和在linux系统中打开摄像头和播放视频的步骤,但还不是很熟练。gdb的退出不知道因为什么原因一直报错,然后发现自己的版本跟看的不一样可能有出入,于是找自己的版本,然后发现学习知识还是在已有信息的基础上找不然自己跟自己找麻烦。
ubantu中的opencv仅靠命令就能打开摄像头拍照及录制视频。也是第一次搞这个,打开摄像头成功的时候泪目,终于成功了失败了很多次,感谢我的室友们,实践过程中出现了很多错误和问题,身边的人几乎都遇到过,完成得还是蛮快的,又学到了新的东西