【自动驾驶/opencv】32.交通灯颜色提取的难点
交通燈顏色識別有難點,因為很多時候,顏色會因為環境而變化,例如下面的紅燈,下圖不用理會右邊的交通燈,因為我調試程序中是限定了id==8641只分析左邊這個,所以右邊這個沒進行處理。
上圖左邊是向左的箭頭燈,右邊是向右的箭頭。但是使用顏色空間進行提取顏色時,這箭頭很亮的部分,其實已經接近白色了,所以就提取不到紅色了。
這張圖是截取亮燈中心帶一點周邊的圖像:
下面這張圖是截取亮燈中心的圖像:【注意,這里我已經附圖了,因為很接近白色,所以人眼不太能看出來,你可以把鼠標移動到下面中心位置的部分,就會出現一個放大鏡的+,這就是圖片】
我們人眼之所以還能覺得它是紅色,是因為箭頭周邊,亮度沒那么強的部分還能看出是紅色,想把這接近白色的部分提取出紅色,自然就不太可能了。
如下圖,是用我另一篇博客HSV提取RBG各種顏色c++代碼來提取紅色得到的圖片。可以看出,紅色亮燈區域并沒提取出來,只有周邊的紅色部分提取出來了:
如果從相機isp方面無法繼續優化,那么就只能從其他顏色以外的角度想辦法來解決了。
下面的方法不是使用hsv提取顏色,所以和上面的HSV方法有所差異:
void ExtractGreenLight(cv::Mat src_img, cv::Mat &dst_img) {std::vector<cv::Mat> Src_Mat_part(src_img.channels());cv::split(src_img, Src_Mat_part);cv::Mat img_green, img_red;img_green = Src_Mat_part[1].clone();img_red = Src_Mat_part[2].clone();dst_img = img_green - img_red; }void ExtractRedLight(cv::Mat src_img, cv::Mat &dst_img) {std::vector<cv::Mat> Src_Mat_part(src_img.channels());cv::split(src_img, Src_Mat_part);cv::Mat img_blue, img_red, img_green;img_blue = Src_Mat_part[0].clone();img_green = Src_Mat_part[1].clone();img_red = Src_Mat_part[2].clone();dst_img = cv::max(img_green, img_red) - cv::min(img_green, img_blue);// dst_img = img_red - cv::min(img_green,img_blue);// dst_img = 2 * img_red - img_blue - 220; }上面兩個函數的輸出是灰度圖像,分別為只包含紅(黃)色和只包含綠色的圖像。代碼提取紅色的函數提取的是紅色和黃色一起提取出來,然后利用紅黃色在交通燈的上下位置來區分紅色和黃色。提取綠色的函數就是只提取綠色。
當然,由于我們可以由目標檢測得到交通燈的box位置,所以可以得到只包含交通燈的roi圖片,對這roi圖片進行顏色提取,可以得到下面這張灰度圖:
可以看出,我們能夠利用強光周圍的紅色,也能找到亮燈區域,只不過,此時亮燈區域是提取不了紅色,所以圖中亮燈區域的左箭頭顯示為黑色。
對上面灰度圖進行二值化,可以得到下面這張圖,下圖的邊界框是我畫出來的,不是二值化后得到的框。然后再找輪廓,找到亮燈區域的box。最后再根據找到的box截取出亮燈區域的roi圖片。
不過,這種情況下的亮燈人眼看著都很模糊,機器想要正確識別也不容易。
在這種情況下,可以特殊情況特殊處理,以下是我的一個思路:
先提取出交通燈圖片最亮的部分,然后再二值化,求輪廓,找出最小外接正矩形 cv::Rect roi = cv::boundingRect(contours[i]);就是亮燈區域的位置,根據最小外接正矩形在交通燈的位置來分類是紅色、黃色、或者綠色。一個交通燈的上中下三個亮燈區域依次是是紅、黃、綠。
當然,對于不是這種交通燈的,該方法就不適用了,畢竟這種方法沒有使用顏色空間,并不能真正從顏色角度提取顏色。
更多細節請跳轉。
總結
以上是生活随笔為你收集整理的【自动驾驶/opencv】32.交通灯颜色提取的难点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【ros】4.rosbag的相关用法
- 下一篇: 【数学和算法】初识卡尔曼滤波器(三)