OpenCV單目視覺定位(測量)系統(新增 含程式碼)
OpenCV單目視覺定位(測量)系統
The System of Vision Location with Signal Camera
Abstract:This passage mainly describes how to locate with signalcamera,which bases on OpenCV library.
Key words: OpenCV; Locate;Signalcamera
摘 要:本文主要描述的是利用開源計算機視覺庫OpenCV實現單目視覺定位系統。
關鍵詞: OpenCV;單位視覺定位
1 總體設計方案
單目視覺定位系統是通過單個解析度為640*480,20萬的USB手動調焦攝像頭獲取圖片並傳到計算機利用OpenCV進行預處理、識別、定位、測量等影象處理演算法,進而得出目標物體相對攝像頭的二維座標距離。
2 預處理
對攝像頭獲取的圖片進行均值濾波處理,目的是抑制電氣元件或者環境因素引起的噪聲。濾波也叫平滑處理,濾波的目的是抑制噪聲,平滑濾波屬於低頻增強空間濾波技術,因為影象的能量大部分集中在幅度譜的低中頻,噪聲一般存在於高頻段。
在本系統中主要採用均值濾波演算法,也叫鄰域平均演算法。領域平均演算法的基本思想是對含噪聲影象的每一個畫素點f(x,y)取領域S,用領域S中所包含的畫素灰度平均值來代替該點的灰度值。
領域平均法的優點是處理方法簡計算速度快,缺點是在降低噪聲的同時是影象產生一定程度的模糊,領域半徑越大,去噪效果越好,但影象越模糊。
因此,本系統採用3 X 3模板h,其轉置矩陣為:1/9 [1,1,1 ; 1,1,1 ; 1,1,1],設f(x,y)為原影象的每一個畫素值,g(x,y)為輸出影象對應的每一個畫素值,則均值濾波核心演算法為原影象的每一個畫素(除影象邊緣畫素)和3 X 3模板h進行卷積運算得出輸出影象。
圖一 灰度圖
圖二 均值濾波
3 識別
對於目標物體的識別,本系統是採用Canny邊緣檢測找出所有可能的邊緣資訊,然後對邊緣資訊進行提取和分析,進而識別出目標物體。與該目標物體的識別還有一種方法是採用閾值演算法分割出特定灰度值範圍內的物體,但該演算法受光照影響較大,而邊緣檢測受光照影響較少,因此Canny採用邊緣檢測演算法。
3.1目標物體
對目標物體的設計,我採用了外面六邊形,裡面五邊形,六邊形與五邊形之間黑色填充,其餘白色填充,六邊形與五邊形中心基本上一致。如下圖所示
圖三列印的目標物體
3.2 Canny邊緣檢測
邊緣檢測的演算法只要是基於影象增強的一階和二階導數。Canny邊緣檢測運算元是JohnF.Canny於1986年開發出來的一個多級邊緣檢測演算法。Canny的目標是找到一個最優的邊緣檢測演算法。其具有的優點是:
l 低錯誤性:標識出盡可能多的實際邊緣,同時儘可能地減少噪聲產生的誤報。
l 高定位性:標識出的邊緣要與影象中的實際邊緣儘可能接近
l 最小效應:影象中的邊緣只能標識一次,並且可能存在的影象噪聲不應標識為邊緣
其步驟是,首先使用高斯平滑濾波器卷積降噪,計算梯度幅值和方向,然後進行非極大值抑制,排除非邊緣畫素,僅僅保留了一些細線條,最後滯後閾值。
對上面經過均值濾波的灰度圖進行Canny邊緣檢測。
圖四 邊緣檢測圖
3.3 輪廓分析
對上面的Canny邊緣檢測得出的資訊運用OpenCV提供的findContours函式邊緣資訊轉化為輪廓資訊,最後再對輪廓進行分析處理,找出目標物體。
圖五 輪廓圖
輪廓分析演算法:遍歷所有輪廓,排除凹輪廓和輪廓面積小於100畫素的輪廓,找出輪廓為逼近六邊形和逼近五邊形的所有輪廓,找出這些逼近六邊形和逼近五邊形輪廓的最小外接矩形,並各提取最小外接矩形的中心(即逼近六邊形和逼近五邊形輪廓中心),若逼近六邊形輪廓的最小外接矩形和逼近五邊形輪廓的最小外接矩形中心基本在同一點(考慮畸變原因,中心點不一定一致),則為目標物體。
3 定位
本系統是採用640*480解析度,20萬畫素的手動調焦的USB攝像頭進行實驗的,該攝像頭廣角較低,畸變不厲害。
定位功能得出的座標是相對於自定義的影象座標原點,在該系統中,定義的原點就是影象中心(320,240)單位為畫素。因此,在攝像頭水平放置的情況下,自定義影象原點即為二維空間上的攝像頭正下方。
定位的基本思想是利用已知目標物體的長度和求出的目標物體的畫素長度,得出畫素的尺寸,再利用畫素尺寸和目標物體在自定義原點的X,Y方向的畫素距離,進而求出目標物體相對水平放置的攝像頭的X,Y方向實際距離。
實驗結果,本實驗是攝像頭距目標物體正上方大約50cm上進行測量的,攝像頭為水平放置。經過多次測量,測出距離與實際距離誤差基本上維持在1cm到2cm之間。如下圖所示:(紅色點為自定義的圖象原點,左上方的Target_X,Target_Y分別為系統測出的目標距原點(攝像頭正下方)的X和Y方向的測出距離。影象上的白色座標系為實際理論距離。
圖六 實驗結果圖
圖、實驗情況
1 結束語
該測量系統只在短範圍內測量,實驗還存在誤差。因為該攝像頭本身畸變不大,沒有進行標定,矯正等一系列處理,實驗資料還能接受,但對於廣角大、畸變大的攝像頭,本系統根本無法適用。還有的是,本系統還沒有進行相機姿態估計,因此,對於攝像頭與水平面有一定角度時,誤差會大大增加。
在接下來的時間裡,作者會盡量完善該系統,爭取能用於無人機以及機器人的單目視覺定位系統。
核心程式碼:
//定位函式
void Location(){
//均值濾波
blur(gray, gray_blur, Size(3, 3));
//邊緣檢測提取邊緣資訊
Canny(gray_blur, dstThreshold, 150, 450);
imshow("canny邊緣檢測", dstThreshold);
//對邊緣影象提取輪廓資訊
vector<vector<Point> >contours;
findContours(dstThreshold, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
//畫出輪廓
drawContours(contours_image, contours, -1, Scalar(0, 0, 255));
imshow("contours", contours_image);
//畫出定義的原點
circle(src, Point2f(oriX, oriY), 2, Scalar(0, 0, 255), 3);
//定義分別逼近六邊形和五邊形的輪廓
vector< vector<Point> > Contour1_Ok, Contour2_Ok;
//輪廓分析
vector<Point> approx;
for (int i = 0; i < contours.size(); i++){
approxPolyDP(Mat(contours[i]), approx, cv::arcLength(cv::Mat(contours[i]), true)*0.04, true);
//去除 小輪廓,只提取凸輪廓
if (std::fabs(cv::contourArea(contours[i])) < 600 || !cv::isContourConvex(approx))
continue;
//儲存逼近六邊形的輪廓 到 Contour1_Ok
if (approx.size() == 6){
Contour1_Ok.push_back(contours[i]);
}
//儲存逼近五邊形的輪廓 到 Contour2_Ok
else if (approx.size() == 5){
Contour2_Ok.push_back(contours[i]);
}
}
//對所有符合要求的六邊形,五邊形輪廓進行分析
//識別出自定義的物體的關鍵是:
//1.六邊形和五邊形輪廓的最小外接矩形的中心基本在同一點
//2.六邊形輪廓的最小外接矩形的任一邊長大於五邊形輪廓的最小外接矩形的任一邊長
for (int i = 0; i < Contour1_Ok.size(); i++){
for (int j = 0; j < Contour2_Ok.size(); j++){
RotatedRect minRect1 = minAreaRect(Mat(Contour1_Ok[i])); //六邊形輪廓的最小外接矩形
RotatedRect minRect2 = minAreaRect(Mat(Contour2_Ok[j])); //五邊形輪廓的最小外界矩形
//找出符合要求的輪廓的最小外接矩形
if ( fabs(minRect1.center.x - minRect2.center.x) < 30 && fabs(minRect1.center.y - minRect2.center.y)<30 && minRect1.size.width > minRect2.size.width){
Point2f vtx[4];
minRect1.points(vtx);
//畫出找到的物體的最小外接矩形
for (int j = 0; j < 4; j++)
line(src, vtx[j], vtx[(j + 1) % 4], Scalar(0, 0, 255), 2, LINE_AA);
//畫出目標物中心到影象原點的直線
line(src, minRect1.center, Point2f(oriX, oriY), Scalar(0, 255, 0), 1, LINE_AA);
//目標物距影象原點的X,Y方向的畫素距離
targetImage_X = minRect1.center.x - oriX;
targetImage_Y = oriY - minRect1.center.y;
line(src, minRect1.center, Point2f(minRect1.center.x, oriY), Scalar(255, 0, 0), 1, LINE_AA);
line(src, Point2f(oriX, oriY), Point2f(minRect1.center.x, oriY), Scalar(255, 0, 0), 1, LINE_AA);
Point2f pointX((oriX + minRect1.center.x) / 2, oriY);
Point2f pointY(minRect1.center.x, (oriY + minRect1.center.y) / 2);
//找出最大邊
float a = minRect1.size.height, b = minRect1.size.width;
if (a < b) a = b;
mm_per_pixel = targetLength / a; //計算畫素尺寸 = 目標物的實際長度(cm)/ 目標物在影象上的畫素長度(pixels)
targetActualX = mm_per_pixel *targetImage_X; //計算實際距離X(cm)
targetActualY = mm_per_pixel *targetImage_Y; //計算實際距離Y(cm)
//列印資訊在圖片上
String text1 = "X:"+format("%f", targetImage_X);
String text2 = "Y:"+format("%f", targetImage_Y);
putText(src, text1, pointX, FONT_HERSHEY_SIMPLEX, 0.4, Scalar(0, 0, 255), 1, 8);
putText(src, text2, pointY, FONT_HERSHEY_SIMPLEX, 0.4, Scalar(0, 0, 255), 1, 8);
String text3 = "Target_X:"+format("%f", targetActualX);
String text4 = "Target_Y:"+format("%f", targetActualY);
putText(src, text3, Point(10,30), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(0, 0, 255), 1, 8);
putText(src, text4, Point(10,60), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(0, 0, 255), 1, 8);
}
break;
}
break;
}
imshow("SRC", src);
}
完整程式碼
http://download.csdn.net/download/chenmohousuiyue/9947409點選開啟連結
相關推薦
OpenCV單目視覺定位(測量)系統(新增 含程式碼)
OpenCV單目視覺定位(測量)系統 The System of Vision Location with Signal Camera Abstract:This passage mainly describes how to locate with signalcame
乾貨 | Matlab實現單目視覺里程計基於SURF特徵(程式碼類)
博主github:https://github.com/MichaelBeechan 博主CSDN:https://blog.csdn.net/u011344545 SURF特徵提取參考:https://blog.csdn.net/u01134454
單目視覺定位測距的兩種方式
單目定位和雙目定位的選擇,我覺得主要還是成本和時間的考慮。之前也嘗試過雙目定位,感覺要更精準些,但雙目測距需要對兩幅影象進行影象變換和極線匹配,稍微耗時了一些。這幾天嘗試了一下單攝像頭進行測距定位,主要有兩個思路: 1.定位測量插值得到每個畫素的實際
OpenCV學習筆記(二十一)——簡單的單目視覺測距嘗試
前言: 視覺測距作為機器視覺領域內基礎技術之一而受到廣泛的關注,其在機器人領域內佔有重要的地位,廣泛應用於機器視覺定位、目標跟蹤、視覺避障等。機器視覺測量主要分為:單目視覺測量、雙目視覺測量、結構光視覺測量等。結構光由於光源的限制,應用的場合比較固定;
基於單目視覺的四旋翼定點降落——如何搭建基於gazebo的pixhawk模擬環境(三)-1
搭建模擬環境是相當重要的,因為我們的程式碼如果直接放到飛機上去跑,那麼很容易炸機。通過模擬環境,我們至少可以保證程式碼邏輯的正確性。這篇文章還是要感謝我的隊友舒仔仔的幫助,話不多說,上正文。1 安裝gazebo一般安裝的ROS就已經自己安裝了gazebo,如果已經安裝
單目視覺(5):SFM之特徵點匹配(四)
SFM之特徵點匹配(四) 引入 在經過對每幅影象進行特徵提取之後,可以發現在一幅影象中存在非常多的特徵點(特殊情況下可能特徵點很少)。那麼如何去找出不同影象中的哪些特徵點反應在現實世界中是同一個物理座標呢?這需要做的工作就是對兩幅影象中的特徵點
基於單目視覺的移動機器人室內定位與運動目標跟蹤
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
OpenCV Using Python——單目視覺三維重建
import cv2 import numpy as np import glob ################################################################################ print 'criteria and object poin
OpenCV Using Python——基於SURF特徵提取和金字塔LK光流法的單目視覺三維重建
基於SURF特徵提取和金字塔LK光流法的單目視覺三維重建 1. 單目視覺三維重建問題 在前面的文章中,筆者用SIFT提取特徵後用radio測試剔除了匹配中異常的特徵點,然後根據匹配合格的特徵點計算基礎矩陣和本徵矩陣,對本徵矩陣SVD分解來估計和構造透視矩陣,
單目視覺SLAM:采用逆深度參數化的方法求取深度信息的過程
ive 魯棒性 圖片 lte 有著 研究 tla 一次 攝像機 一種實時的單目視覺SLAM改進算法 該算法采用一個攝像頭作為外部傳感器來提取機器人行進過程中周圍環境的特征信息,用實時性良好的FAST提取環境特征點,結合逆深度參數化進行特征點非延時初始化,用壓縮擴展卡爾曼濾波
python 單目視覺測距
# import the necessary packages import numpy as np import cv2 import sys reload(sys) sys.setdefaultencoding('utf8') cap = cv2.VideoCaptu
2.單目視覺演算法
演算法流程 建立影象塊 → 根據相機光心確定搜尋極線 → 極線搜尋演算法 → 深度濾波器進行濾波 → 得到對應畫素後,進行三角測量 → 得到深度資訊 如何匹配? 極線搜尋和塊匹配 匹配結果優化? 深度濾波器技術 三角測
無人駕駛視覺-單目視覺里程計
対極幾何 通過兩幀影象的運動,利用匹配點,求解相機的位姿變換。(就是得到R,t)步驟: 1. 根據配對點的畫素位置,求出 E 或者 F ; 2. 根據 E 或者 F ,求出 R, t。 問題 單目視覺的尺度不確定性(Scale Ambiguity)。例如,程式中
opencv 單目相機標定 自帶例子程式的使用
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/
單目視覺標定:世界座標系、相機座標系、影象座標系、畫素座標系——簡單粗暴,粗暴
1.正文 影象處理、立體視覺等等方向常常涉及到四個座標系:世界座標系、相機座標系、影象座標系、畫素座標系。例如下圖: 構建世界座標系只是為了更好的描述相機的位置在哪裡,在雙目視覺中一般將世界座標系原點定在左相機或者右相機或者二者X軸方向的中點。 接下來的重點,就是關於
基於單目視覺的智慧車輛視覺導航系統設計
基於計算機視覺的高速公路防撞系統是當前智慧交通管理系統研究的熱點之一。如何在多變的環境下快速準確地從視訊影象裡檢測到車道和前方車輛是實現這類系統面臨的最關鍵問題。近20年來,國內外很多研究人員對這個問題進行了大量研究,提出了多種多樣的實用演算法併成功開發了一些視覺系統。這
非濾波單目視覺slam筆記1
非濾波單目視覺slam 主要分為以下8部分 資料型別 資料關聯 初始化 位姿估計 地圖維護 地圖生成 失效恢復 迴環檢測 資料型別 直接法(稠密,半稠密) 基本原理是亮度一致性約束,\(J(x,y) = I(x + u(x,y)+ v(x,y))\) ,x,y是影象的畫素座標,u,v是同一場景下的兩幅
OpenCV——單目相機標定
步驟: 1、製作標定板 此處製作邊長2.5cm的棋盤圖,規格大小為8*8,生成程式碼如下所示 //程式設計環境:VS2013, X64,OpenCV3.0.0 #include <iostream> #include <opencv2\
Java併發程式設計(2):執行緒中斷(含程式碼)
使用interrupt()中斷執行緒當一個執行緒執行時,另一個執行緒可以呼叫對應的Thread物件的interrupt()方法來中斷它,該方法只是在目標執行緒中設定一個標誌,表示它已經被中斷,並立即返回。這裡需要注意的是,如果只是單純的呼叫interrupt()方法,執行緒並沒有實際被中斷,會繼續往下執行。
Java併發程式設計(3):執行緒掛起、恢復與終止的正確方法(含程式碼)
JAVA大資料中高階架構 2018-11-06 14:24:56掛起和恢復執行緒Thread 的API中包含兩個被淘汰的方法,它們用於臨時掛起和重啟某個執行緒,這些方法已經被淘汰,因為它們是不安全的,不穩定的。如果在不合適的時候掛起執行緒(比如,鎖定共享資源時),此時便可能會發生死鎖條件——其他執行緒在等待該