嵌入式系统调制
-
- 前言
- 一、代码的GDB调试
-
- 1. GDB的使用
- 2. GDB的调试
-
- ① GDB编译
- ② 段错误调试
- 3. GDB的常用命令
-
- ① list命令
- ② run命令
- ③ break命令
- ④ print命令
- 二、Opencv的使用
-
- 1. opencv4.5.0的安装
- 2. 使用opencv进行编译
- 3. opencv打开摄像头
- 总结
- 附录
-
- 一、GDB常用命令
- 二、opencv常用方法及功能
前言
OpenCV是Intel开元计算机视觉库,它有一系列开源的C函数和少量C++类构成,实现了图像处理和计算机视觉很多通用的算法。
OpenCV特点:
1.拥有包括300多个C函数的跨平台的中、高层API;
2.跨平台:Windows/Linux;
3.Free:无论是对于商业还是非商业应用;
4.速度快;
5.使用方便。
一、代码的GDB调试
GDB : GNU Debugger,是GNU工程为GNU操作系统开发的调试器,但它的使用不局限于GNU操作系统, GDB可以运行在UNIX、Linux甚至Microsoft Windows。
使用GDB我们可以:
– 设置断点使程序停住
– 监视或修改程序中变量的值
– 跟踪代码执行过程
1. GDB的使用
• 程序要能被调试,必须包含调试信息
• 编译程序时,通过gcc的-g选项为程序添加调试信息,例如:
gcc –g –o helloworld helloworld.c
- GDB的启动
打开终端输入gdb
启动完成
2. GDB的调试
① GDB编译
下面的代码实现对一个整型数的反转功能,比如输入123,则输出321
#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);
}
使用GDB编译以上代码
gcc -g -o Revert Revert.c
编译成功
发现已生成可执行文件Revert
使用GDB运行Revert文件
执行成功
② 段错误调试
但是在有些情况下会出现段错误
示例代码:
#include<stdio.h>
#include<string.h>
#define BUFSIZE 256
static char acBuf[BUFSIZE];
static char *pStr;
int main(void)
{
printf("请输入一个字符");
gets(pStr);
printf("\n你的字符是:%s\n",pStr);
}
编译后发现出现段错误
段错误调试可以参考linux环境下使用gbd调试段错误
3. GDB的常用命令
① list命令
在gdb中运行list命令(缩写l)可以列出代码
创建一段示例代码
#include<stdio.h>
int add(int a, int b)
{
return a + b;
}
int main()
{
int sum[10] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
} ;
int i;
int array1[10] =
{
48, 56, 77, 33, 33, 11, 226, 544, 78, 90
};
int array2[10] =
{
85, 99, 66, 0x199, 393, 11, 1, 2, 3, 4
};
for (i = 0; i < 10; i++)
{
sum[i] = add(array1[i], array2[i]);
}
}
list的具体形式包括:
- list < linenum > ,显示程序第linenum行周围的源程序,如:
- list < function > ,显示函数名为function的函数的源程序,如:
当行数不足时,将会显示最后几行代码
② run命令
在gdb中,运行程序使用run命令
在程序运行前,我们可以设置如下4方面的工作环境:
- 程序运行参数
set args 可指定运行时参数,如:set args 10 20 30 40 50;show args 命令可以查看设置好的运行参数。
- 运行环境
path
可设定程序的运行路径;how paths可查看程序的运行路径;set environment varname [=value]用于设置环境变量,如set env USER=baohua;
show environment [varname]则用于查看环境变量。
- 工作目录
cd 相当于shell的cd命令;pwd 显示当前所在的目录。
- 程序的输入输出
info terminal 用于显示程序用到的终端的模式;
gdb中也可以使用重定向控制程序输出,如run > outfile;
tty命令可以指定输入输出的终端设备,如:tty /dev/ttyS1。
③ break命令
在gdb中用break命令来设置断点
设置断点的方法包括:
- break < function >
在进入指定函数时停住,C++中可以使用class::function或function(type, type)格式来指定函数名。
- break < linenum >
在指定行号停住。
- info breakpoints [n] / info break [n] 可查看断点 运行至断点,使用 whatis 函数查看iNum变量类型
④ print命令
在调试程序时,当程序被停住时,可以使用print命令(缩写为p),或是同义命令inspect来查看当前程序的运行数据
print命令的格式是:
print <expr>
print /<f> <expr>
当程序停住时,或是单步跟踪时,这些变量会自动显示。 如果要修改变量,如x的值,可使用如下命令:
print x=4
x=4
二、Opencv的使用
1. opencv4.5.0的安装
opencv安装参考教程如下:
ubuntu16.04安装opencv3.4.1教程
2. 使用opencv进行编译
打开命令窗口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.jpg");
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;
}
保存并编译
这一步要注意test文件的路径和类型要与代码一致
运行test.cpp
./test
3. opencv打开摄像头
参考代码:
#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;
}
有几项需要注意
1) 如果要求打开你硬盘上一个视频文件来播放,请问第7行代码如何修改?
2)在第9行的while循环中,Mat是一个什么数据结构? 为什么一定要加一句waitKey延时代码,删除它行不行?
- 如果需要打开硬盘上一个视频文件来播放,第7行代码应改为
/home/Download/ awsl.avi
3)此代码会在while循环中一直运行,你如果试图用鼠标关闭图像显示窗口,会发现始终关不掉。需要用键盘Ctrl+C 强制中断程序,非常不友好。如何改进?
- Mat是一个类。由两部分数据组成:矩阵头(包括矩阵尺寸、存储方法、存储地址等信息)和一个指向所有像素值的矩阵(根据所选存储方法不同,矩阵可以是不同的维数)的指针。
- waitKey延时越长 fps越小 出现跳帧 摄像头显示变卡,故要有一定的延时,可以加一个break代码,如if(ch == 27) break;
参考代码<打开摄像头采集并保存>
/*********************************************************************
打开电脑摄像头,空格控制视频录制,ESC退出并保存视频RecordVideo.avi
*********************************************************************/
#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();
}
打开摄像头效果如下:
动图演示:
总结
这次GDB及Opencv操作遇到了许多错误
解决方法如下:
使用
(gdb) next
代替
(gdb) s
便可解决
这是由于gedit命令自动在根目录生成文件,将
gcc test.cpp
改为
g++ /test.cpp
即可解决
附录
一、GDB常用命令
命 令 | 解 释 | 示 例 |
---|---|---|
file <文件名> | 加载被调试的可执行程序文件。 因为一般都在被调试程序所在目录下执行GDB,因而文本名不需要带路径 | (gdb) file gdb-sample |
r | Run的简写,运行被调试的程序.如果此前没有下过断点,则执行完整个程序; 如果有断点,则程序暂停在第一个可用断点处。 | (gdb) r |
c | Continue的简写,继续执行被调试程序,直至下一个断点或程序结束。 | (gdb) c |
s, n | s: 执行一行源程序代码,如果此行代码中有函数调用,则进入该函数; n: 执行一行源程序代码,此行代码中的函数调用也一并执行。 | (gdb) file gdb-sample |
b <行号> b <函数名称> b *<函数名称> b *<代码地址> d [编号] | b: Breakpoint的简写,设置断点。两可以使用“行号”“函数名称”“执行地址”等方式指定断点位置。 其中在函数名称前面加“*”符号表示将断点设置在“由编译器生成的prolog代码处”。如果不了解汇编,可以不予理会此用法。 d: Delete breakpoint的简写,删除指定编号的某个断点,或删除所有断点。断点编号从1开始递增。 | (gdb) b 8 (gdb) b main (gdb) b *main (gdb) b *0x804835c (gdb) d |
二、opencv常用方法及功能
1、cvLoadImage:将图像文件加载至内存;
2、cvNamedWindow:在屏幕上创建一个窗口;
3、cvShowImage:在一个已创建好的窗口中显示图像;
4、cvWaitKey:使程序暂停,等待用户触发一个按键操作;
5、cvReleaseImage:释放图像文件所分配的内存;
6、cvDestroyWindow:销毁显示图像文件的窗口;
7、cvCreateFileCapture:通过参数设置确定要读入的AVI文件;
8、cvQueryFrame:用来将下一帧视频文件载入内存;
9、cvReleaseCapture:释放CvCapture结构开辟的内存空间;
10、cvCreateTrackbar:创建一个滚动条;
11、cvSetCaptureProperty:设置CvCapture对象的各种属性;
12、cvGetCaptureProperty:查询CvCapture对象的各种属性;
整理至Opencv常用方法