Ubuntu上的GDB调试以及使用opencv对图像处理和录像

提示:本文为课程作业,存在很多不足。



提示:以下是本篇文章正文内容,下面案例可供参考

一、GDB调试

1.GDB简介
•GDB : GNU Debugger,是GNU工程为GNU操作系统开发的 调试器,但它的使用不局限于GNU操作系统, GDB可以运行 在UNIX、Linux甚至Microsoft Windows。
• GDB可以调试C、C++、Objective-C、Pascal、Ada等语言编 写的程序;被调试的程序可以跟GDB运行于同一台电脑,也可 运行于不同电脑。

• 使用GDB我们可以:
– 设置断点使程序停住
– 监视或修改程序中变量的值
– 跟踪代码执行过程

2.gdb的使用
•程序要能被调试,必须包含调试信息
• 编译程序时,通过gcc的-g选项为程序添加调试信息,
例如: gcc –g –o helloworld helloworld.c

3.gdb命令

GDB命令 作用
file 装入想要调试的可执行文件
kill 终止正在调试的程序
list 列出产生执行文件的源代码的一部分
next 执行一行源代码但不进入函数内部
step 执行一行源代码而且进入函数内部
run 执行当前被调试的程序。
c 继续运行程序
quit 终止gdb
watch 使你能监视一个变量的值而不管它何时被改变
backtrace 栈跟踪,查出代码被谁调用
print 查看变量的值
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给调用者

break命令的使用
– 根据行号设置断点:
• (gdb) break linenum
– 根据函数名设置断点:
• (gdb) break funcname
– 执行非当前源文件的某行或某函数时停止执行:
• (gdb) break filename:linenum
• (gdb) break filename:funcname
– 根据条件停止程序执行:
• (gdb) break linenum if expr
• (gdb) break funcname if expr

GDB调试练习

Linux中,程序崩溃时,一般会产生core文件,记录进程退出前 的状态,调试段错误问题,借助于该文件,可快速定位问题。
• 可按如下步骤生成和使用core文件
– Step 1: 让系统产生core文件 • ulimit –c num #设定core文件容量(num为数字,为0 是不产生core文件)
– Step 2: 运行程序,让程序崩溃,从而生成core文件
– Step 3: gdb配合core文件,定位问题 • gdb 程序名 core文件名 • 比如: gdb segDemo core

1.创建文件

mkdir gdb
cd gdb
touch test1.c
gedit test1.c

在这里插入图片描述

2.编写文件

#include<stdio.h>
int main()
{
    
    
  int *p=0;
  *p=1;
  return 0;
}

3.执行

在这里插入图片描述

找到问题所在:

在这里插入图片描述

二、在Ubuntu系统下编译Opencv3.4.1

**

1.安装Opencv3.4.1

**

安装编译教程点击这里==>Windows10&Ubantu16.04&树莓派3B+安装opencv教程

在这里插入图片描述
执行这步出现问题点击下方链接

Ubuntu18.04下安装OpenCv依赖包libjasper-dev无法安装的问题

在这里插入图片描述
在这里插入图片描述
执行这两步出现警告(不支持设置属性等。。。)为正常现象,无需更改。

2.编译Opencv3.4.1

在这里插入图片描述

gedit 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.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;
}

>过程中遇到的问题及解决方法

把照片放到mytest文件目录下且修改名字为lena.jpg

在这里插入图片描述

或者修改下方代码lena为图片名称(原代码第九行)

在这里插入图片描述

对main未定义
在这里插入图片描述

这里修改指令为

g++ /test.cpp -o test `pkg-config --cflags --libs opencv`

遇到新问题
在这里插入图片描述
输入以下代码(会自动安装,过程中点击y执行即可)

sudo apt-get install libcanberra-gtk-module

在这里插入图片描述
>成功编译

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、使用opencv库编写打开摄像头压缩视频的程序

1.正常打开摄像头及问题汇总

首先执行命令:

cd opencv-3.4.1
cd 123
touch test2.cpp
sudo gedit /test2.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++ /test2.cpp -o test2 `pkg-config --cflags --libs opencv`
./test2

在这里插入图片描述
可以看到摄像头正常打开

>过程中遇到的问题及解决方法:

1.在可移动设备中无法找到摄像头选项
在这里插入图片描述

解决方法:在虚拟机设置中设置usb选项=>选择usb3.0=>点击下方确认然后重启系统
在这里插入图片描述
在这里插入图片描述

2.运行程序后还是无法出现摄像头

1.程序错误
2.没有在执行命令之前连接摄像头

3.连接摄像头显示驱动错误(我自己就是这个原因导致花了接近两个小时在找问题)
我们需要先查看是否是Vmware usb device设备缺失
右击我的电脑=>点开属性=>找到左上方的设备管理器=>查看通用串行总线控制器=>查看是否有Vmware usb device
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果没有Vmware usb device,则我们需要重新安装Vmware Tools(在虚拟机开机时点击)
在这里插入图片描述
安装Vmware Tools传送门

安装好后重启系统就i可以用摄像头了

PS:各种问题解决传送门

VMware下提示USB连接失败,驱动程序错误

虚拟机中无法显示摄像头驱动问题

虚拟机中无法识别摄像头USB设备问题

虚拟机中无法识别电脑摄像头和usb摄像头

2.打开摄像头进行录像

首先执行命令:

cd opencv-3.4.1
cd 123
touch test3.cpp
sudo gedit /test3.cpp

编写程序:

#include<iostream>
#include <opencv2/opencv.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;

int main()
{
    
    
	//打开电脑摄像头
	VideoCapture cap(0);
	if (!cap.isOpened())
	{
    
    
		cout << "error" << endl;
		waitKey(0);
		return 0;
	}

	//获得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++ /test3.cpp -o test3 `pkg-config --cflags --libs opencv`
./test3

点击esc退出录像
录像截图
在这里插入图片描述
在这里插入图片描述
在对应文件夹生成了视频
在这里插入图片描述

3.问题解答

1)如果要求打开你硬盘上一个视频文件来播放,请问示例代码1第7行代码如何修改?

将括号里的0改为路径+视频名

VideoCapture capture(0);
VideoCapture capture(路径+视频名);

2)在示例代码1第9行的while循环中,Mat是一个什么数据结构? 为什么一定要加一句waitKey延时代码,删除它行不行?

Mat有两部分组成
头部:存储方式、图像大小等信息,头部的大小是一个常量(constant)
数据块:图像像素的值(按行顺序存储)
Mat 数据结构详细介绍

waitKey函数用于显示的延迟。例如,waitKey(0)将无限显示窗口,直到按下任意按键退出延迟事件(适用于显示图像)。如果delay大于0,例如,waitKey(25)将每隔至少25ms显示视频的一帧图像(适用于显示视频帧),如果要按键退出,则需要将waitKey(25)与一个按键值(ASCII码)比较.
OpenCV:延迟函数waitKey()详细介绍

不能删除

3)示例代码1代码会在while循环中一直运行,你如果试图用鼠标关闭图像显示窗口,会发现始终关不掉。需要用键盘Ctrl+C 强制中断程序,非常不友好。如何改进?

改进方法还没研究出来(学渣的无奈),可以查看大佬们的相关方法。


总结

本次实验过程中出现的问题很多,而且救我自己遇到的问题而言,比其他铜须遇到的更多,解决起来也更加的棘手,花费了大量的时间取解决这些问题,不过相应的,我也从中收获了很多。

猜你喜欢

转载自blog.csdn.net/aiwr_/article/details/109339662