ROS系統(tǒng)下調(diào)用OpenCV:FAST特征檢測算子

在我上一篇文章中說到悯搔,要在無人機上跑視覺算法照激。而團隊師兄的方案是程序運行在ROS系統(tǒng)下霎冯,這樣控制和視覺分離铃拇,比較好分工。ROS是什么沈撞?機器人操作系統(tǒng)(Robot Operating System, ROS)是一個應用于機器人上的操作系統(tǒng),它操作方便慷荔、功能強大,特別適用于機器人這種多節(jié)點多任務的復雜場景。 因此自ROS誕生以來,受到了學術(shù)界和工業(yè)界的歡迎,如今已經(jīng)廣泛應用于機械臂缠俺、移動底盤显晶、無人機、無人車等許多種類的機器人上壹士。本文以一個簡單的在ROS下調(diào)用opencv的demo供讀者學習~~

ROS Kinetic

1.運行環(huán)境
  • Ubuntu16.04 LTS
  • ROS Kinetic
  • opencv3.3 & contribe
  • Roboware studio (ROS的一個IDE磷雇,strongly recommended
2.創(chuàng)建工作空間

使用Roboware創(chuàng)建以下層次結(jié)構(gòu),教程可參照網(wǎng)上的其他教程躏救。


工作空間
  • vision_pac文件夾表示一個包(package)唯笙,package是ROS源代碼存放的地方,任何ROS的代碼無論是C++還是Python都要放到package中,這樣才能正常的編譯和運行。

  • src中存放的是C++和Python源代碼盒使,這里每一個.cpp文件都是一個節(jié)點(node)崩掘。從功能角度來說,通常一個node負責者機器人的某一個單獨的功能。由于機器人的功能模塊非常復雜,我們往往不會把所有功能都集中到一個node上,而會采用分布式的方式,把雞蛋放到不同的籃子里少办。自然呢堰,節(jié)點之間會通過各種方法來進行通信,ROS中有兩種凡泣,一種是topic通信枉疼,另一種是service通信。本文中使用的是topic通信鞋拟。

  • ROS平臺始終的是cmake工具進行編譯骂维,并且ROS對cmake進行擴展,于是便有了Catkin編譯系統(tǒng)贺纲。CMakeLists.txt原本是Cmake編譯系統(tǒng)的規(guī)則文件,而Catkin編譯系統(tǒng)基本沿用了CMake的編譯風格,只是針對ROS工程添加了一些宏定義航闺。所以在寫法上,catkin的 CMakeLists.txt 與CMake的基本一致。這個文件直接規(guī)定了這個package要依賴哪些package,要編譯生成哪些目標,如何編譯等等流程猴誊。Roboware幫我們完成了大部分工作潦刃,不需要關(guān)心這個文件的具體編寫。

  • pacakge.xml 包含了package的名稱懈叹、版本號乖杠、內(nèi)容描述、維護人員澄成、軟件許可胧洒、編譯構(gòu)建工具畏吓、編譯依賴、運行依賴等信息卫漫。 rospack find菲饼、rosdep 等命令能快速定位和分析出package的依賴項信息,原因就是直接讀取了每一個pacakge中的 package.xml文件列赎。

3.算法原理

這次的demo中宏悦,使用的算法是FAST特征檢測。FAST特征檢測算子基于Harris角點檢測包吝,它簡化了Harris檢測算子的過程饼煞。Harris檢測算子本質(zhì)上是對像素點創(chuàng)建一個窗口,并對周圍各個方向求導漏策。如果垂直的兩個方向上變化很大派哲,就判定為角點。其中用到協(xié)方差矩陣掺喻,特征值分解之類的理論芭届,數(shù)學不好就不誤人子弟了。感耙。褂乍。但可以確定的是,求導是很消耗計算資源的即硼,而且尋找特征點往往只是復雜檢測流程中的一步逃片。于是,就有了FAST算子只酥。
FAST特征檢測算法來源于corner的定義褥实,這個定義基于特征點周圍的圖像灰度值,檢測候選特征點周圍一圈的像素值裂允,如果候選點周圍領(lǐng)域內(nèi)有足夠多的像素點與該候選點的灰度值差別夠大损离,則認為該候選點為一個特征點。


FAST绝编,圖中為FAST-16

上圖中選擇了周圍的16個像素點僻澎,稱為FAST-16角點檢測器。opencv中的FAST默認為FAST-9十饥,當然你可以通過在構(gòu)建檢測器實例時指定FAST檢測器的類型窟勃。

4.代碼編寫

1)先定義location.msg中的數(shù)據(jù)結(jié)構(gòu)。通信的數(shù)據(jù)是一個二維坐標逗堵。

uint32 x
uint32 y

2)vision.cpp文件調(diào)用FAST特征檢測算子秉氧,并發(fā)送給controller

/*******************************************************************
 * Created by 楊幫杰 on 9/21/18
 * Right to use this code in any way you want without warranty,
 * support or any guarantee of it working
 * E-mail: yangbangjie1998@qq.com
 * Association: SCAU 華南農(nóng)大空機團
 ******************************************************************/

#include <ros/ros.h>
#include <vision_pac/location.h>        //自定義msg產(chǎn)生的頭文件
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

#define PATH "/home/jacob/下載/bench1.jpg"

void ProcessImage(Mat& input, Mat& output, vector<KeyPoint>& points)
{
    points.clear();
    //創(chuàng)建FAST特征檢測器,閾值為70
    Ptr<FastFeatureDetector> ptrFAST = FastFeatureDetector::create(70);
    ptrFAST->detect(input,points);
    drawKeypoints(input,points,output,Scalar::all(-1)); //在output上畫出角點位置
    imshow("output",output);
    waitKey(10);
}

void PublishMsg(vision_pac::location &loc,ros::Publisher &pub,vector<KeyPoint>& points)
{
    for(vector<KeyPoint>::iterator it = points.begin(); it != points.end(); it++)
    {
        loc.x = it->pt.x;
        loc.y = it->pt.y;
        pub.publish(loc);//發(fā)布
    }
}

int main(int argc, char **argv)
{
    ros::init(argc, argv, "vision");        //用于解析ROS參數(shù),第三個參數(shù)為本節(jié)點名
    ros::NodeHandle nh;             //實例化句柄,初始化node
    vision_pac::location msg;       //自定義location消息并初始化 
    //創(chuàng)建publisher,往"location_info"話題上發(fā)布消息
    ros::Publisher  pub = nh.advertise<vision_pac::location>("location_info",100);  
    ros::Rate loop_rate(1.0);           //定義發(fā)布的頻率,1HZ
    Mat inputImage = imread(PATH);
    Mat outputImage = Mat::zeros(inputImage.size(),inputImage.type());
    vector<KeyPoint> keypoints; 
    while(ros::ok)          //循環(huán)發(fā)布msg
    {
        //計算一幀使用的時間
        double time1 = static_cast<double>(getTickCount());
        ProcessImage(inputImage,outputImage,keypoints); //對圖像進行處理
        time1=((double)getTickCount()-time1)/getTickFrequency();//計算程序運行時間
        cout<<"一幀處理時間為"<<time1<<"s"<<endl;//輸出運行時間
        PublishMsg(msg,pub,keypoints); //發(fā)布消息
        loop_rate.sleep();//根據(jù)前面的定義的loop_rate,設(shè)置1s的暫停           
    }
    return 0;
}

由于定義了location類型的消息砸捏,可以理解為定義了一個結(jié)構(gòu)體谬运,如

struct location
{
    int x;
    int y;
}

所以隙赁,可以通過這樣的方式定義用于通信的數(shù)據(jù)結(jié)構(gòu)

vision_pac::location msg; 

ROS節(jié)點的初始化十分簡潔易懂垦藏,在官方wiki上說明詳細梆暖。值得一提的是有時會發(fā)現(xiàn)通信丟包的情況(節(jié)點之間的通信是基于TCP/IP協(xié)議棧的)。一開始以為是ROS的bug掂骏,后來發(fā)現(xiàn)是因為緩沖區(qū)太小的原因轰驳。。弟灼。级解。所以程序出問題多找找自己的原因,尤其像我這種菜雞- -田绑!

ros::Publisher  pub = nh.advertise<vision_pac::location>("location_info",100); 

上面這條語句中勤哗,定義了一個Publisher。定義好的Publisher對象通過publish方法就可以把上面定義的msg發(fā)送出去掩驱。其中句柄nh的advertise方法中的泛型接口定義了發(fā)送出去的數(shù)據(jù)結(jié)構(gòu)芒划,第一個參數(shù)定義了topic的名字,第二個則是緩沖區(qū)的大小欧穴。緩沖區(qū)大小要特別注意民逼,當一次發(fā)送多個msg時如果太小就會丟包。

3)controller.cpp中接受消息


/*******************************************************************
 * Created by 楊幫杰 on 9/21/18
 * Right to use this code in any way you want without warranty,
 * support or any guarantee of it working
 * E-mail: yangbangjie1998@qq.com
 * Association: SCAU 華南農(nóng)大空機團
 ******************************************************************/
 
#include <ros/ros.h>
#include <vision_pac/location.h>

void msgCallback(const vision_pac::location::ConstPtr &msg)
{       
    int pointX,pointY;
    pointX = msg->x;
    pointY = msg->y;
    ROS_INFO("Controller:x = %d, y = %d",pointX,pointY);    //輸出
}
int main(int argc, char **argv)
{
    ros::init(argc, argv, "controller");
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("location_info", 100, msgCallback);//設(shè)置回調(diào)函數(shù)msgCallback
    //ros::spin()用于調(diào)用所有可觸發(fā)的回調(diào)函數(shù),將進入循環(huán),不會返回,類似于在循環(huán)里反復調(diào)用spinOnce()    
    //而ros::spinOnce()只會去觸發(fā)一次
    ros::spin();    
    return 0;
}

相應地涮帘,定義Subcriber對象去訂閱主題拼苍,并指定緩沖區(qū)大小和回調(diào)函數(shù)〉饔В回調(diào)函數(shù)會接收到msg并作為一個引用參數(shù)去讀寫疮鲫。

ROS_INFO("Controller:x = %d, y = %d",pointX,pointY);

上面這條語句相當于c語言中的格式輸出printf,會在終端中輸出相應消息弦叶。當然STL中的iostream也是可以使用的俊犯。

ros::spin(); 

而這條語句會阻塞線程,并不斷檢查是否有msg接收湾蔓,有則調(diào)用回調(diào)函數(shù)瘫析。如果不執(zhí)行這條語句,程序就直接return了。

5.結(jié)果驗證
檢測出來的角點

處理時間

角點坐標點

這篇文就至此為止了~~ROS還是很具有進步性的,庫和IDE都讓人有不錯的編程體驗梯醒。值得一提的是寿冕,ROS由于實時性欠佳,工業(yè)上很少使用流昏。最近出了ROS-Industrial ,就是用于工業(yè)機器人的ROS。有時間去了解一下~

Reference:
Harris角點檢測原理詳解
OpenCV學習筆記(四十六)——FAST特征點檢測features2D
學習opencv3(中文版) —— Adrian Kaehler & Gary Bradski
opencv計算機視覺編程攻略(第三版) —— Robert
中國大學MOOC---《機器人操作系統(tǒng)入門》課程講義

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末奇适,一起剝皮案震驚了整個濱河市坟比,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌嚷往,老刑警劉巖葛账,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異皮仁,居然都是意外死亡籍琳,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門贷祈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來趋急,“玉大人,你說我怎么就攤上這事势誊∥卮铮” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵粟耻,是天一觀的道長查近。 經(jīng)常有香客問我,道長勋颖,這世上最難降的妖魔是什么嗦嗡? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮饭玲,結(jié)果婚禮上侥祭,老公的妹妹穿的比我還像新娘。我一直安慰自己茄厘,他們只是感情好矮冬,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著次哈,像睡著了一般胎署。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上窑滞,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天琼牧,我揣著相機與錄音,去河邊找鬼哀卫。 笑死巨坊,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的此改。 我是一名探鬼主播趾撵,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼共啃!你這毒婦竟也來了占调?” 一聲冷哼從身側(cè)響起暂题,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎究珊,沒想到半個月后薪者,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡苦银,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年啸胧,在試婚紗的時候發(fā)現(xiàn)自己被綠了赶站。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幔虏。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖贝椿,靈堂內(nèi)的尸體忽然破棺而出想括,到底是詐尸還是另有隱情,我是刑警寧澤烙博,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布瑟蜈,位于F島的核電站,受9級特大地震影響渣窜,放射性物質(zhì)發(fā)生泄漏铺根。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一乔宿、第九天 我趴在偏房一處隱蔽的房頂上張望位迂。 院中可真熱鬧,春花似錦详瑞、人聲如沸掂林。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泻帮。三九已至,卻和暖如春计寇,著一層夾襖步出監(jiān)牢的瞬間锣杂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工番宁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留元莫,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓贝淤,卻偏偏與公主長得像柒竞,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子播聪,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容