嵌入式程式調試與opencv圖像庫
- 一、在Ubuntu系統上練習程式代碼的GDB調試。
-
- 1. GDB簡介
- 2. gdb的使用
- 3. gdb指令
- 4. gbd調試舉例
- 二、“學了opencv,媽媽再不擔憂你不會圖像程式設計啦!”
-
- 1. 在Ubuntu下安裝OpenCV
- 2. 在Ubuntu下編寫一個打開圖檔進行特效顯示的代碼
- 3. 在windows下安裝OpenCV
- 4. 練習使用opencv庫編寫程式
一、在Ubuntu系統上練習程式代碼的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指令
• 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
4. gbd調試舉例
下面的代碼實作對一個整型數的反轉功能,比如輸入123,則輸出321。
但輸入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);
}
步驟如下:
(1)編譯檔案,并通過gdb進行調試

(2)
(3)
(4)
注意這裡出現了一個問題:printf.c:No such file or directory.
出現這個問題的原因是:debugg檔案的目錄在别的地方(通過指令
show debug-file-directory
可以看出),需要執行指令
set debug-file-directory
然後重新運作gdb調試程式
(5)
通過調試程式我們發現,當iNum的值為10 以後,程式結束了運作,是以輸出結果為010而不是正常的逆序001,我們隻需要将while循環的條件改為
while(iNum >= 10)
即可
二、“學了opencv,媽媽再不擔憂你不會圖像程式設計啦!”
在Ubuntu系統下練習編譯、安裝著名的C/C++圖像處理開源軟體庫 Opencv 。
1. 在Ubuntu下安裝OpenCV
該過程請參考在 Ubuntu系統下安裝 OpenCV 全過程
2. 在Ubuntu下編寫一個打開圖檔進行特效顯示的代碼
步驟如下:
(1)在OpenCV的安裝目錄下建立一個新檔案夾mytest,并建立一個test.cpp檔案;
把圖檔直接放在home路徑下,并複制一份在mytest檔案夾中
cd opencv-3.4.8
mkdir mytest
touch test.cpp
sudo gedit /test.cpp
(2)
編輯以下代碼:
#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("psb.png", src);
cvNamedWindow("test",1); imshow("test", src);
cvWaitKey();
return 0;
}
(3)儲存并編譯
g++ test.cpp -o test `pkg-config --cflags --libs opencv`
(4)運作
./test
3. 在windows下安裝OpenCV
(1)在官網下載下傳并安裝OpenCV:官網連結
(2)配置系統環境變量:
找到OpenCV安裝路徑中的:\opencv\build\x64\vc15\bin
将整個路徑複制并添加到系統環境變量中
(3)重新開機電腦
4. 練習使用opencv庫編寫程式
步驟如下:
(1)編譯一個開啟攝像頭并錄制視訊的程式
#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++ camtest.cpp -o camtest `pkg-config --cflags --libs opencv`
./camtest