楊 豪 盧興來 胡利軍 李從初 顏宗華 徐振宇 姚浩立
(1.寧波市氣象網(wǎng)絡與裝備保障中心,浙江 寧波 315012; 2.浙江省大氣探測技術保障中心,浙江 杭州 310017)
利用圖像識別技術的積雪輔助判別
楊 豪1盧興來2胡利軍1李從初1顏宗華1徐振宇1姚浩立1
(1.寧波市氣象網(wǎng)絡與裝備保障中心,浙江 寧波 315012; 2.浙江省大氣探測技術保障中心,浙江 杭州 310017)
提出了一種基于開源計算機視覺庫OpenCV的圓形檢測方法協(xié)助訂正自動雪深儀的疑誤數(shù)據(jù)。對測雪板上的圖像識別區(qū)域依序進行平滑濾波處理、邊緣檢測、Hough變換圓檢測,識別出積雪情況。利用該方法,提高了疑誤數(shù)據(jù)的訂正效率。
雪深;圖像識別;OpenCV;Hough
近年來,浙江省先后建成了160余套自動雪深觀測儀,在浙江省冰雪災害監(jiān)測中發(fā)揮了重要作用。然而,在實際應用中,發(fā)現(xiàn)存在一些錯誤數(shù)據(jù)。本文從圖像處理的角度出發(fā),對積雪深度圖進行有效判別,從而剔除錯誤數(shù)據(jù)。
大部分雪深觀測儀的基本原理是利用激光單點測距來測量積雪深度,主要傳感器就是激光測距單元。安裝時在立柱上固定好測距單元,在立柱前正對著測距單元的地面上安裝柵格型測雪板,確保測雪面的水平。調(diào)整測距單元使紅色激光點照在測雪板中心的圓形測雪點上,以便標定雪深觀測基準面,保證雪深觀測的準確性。
在冬季下雨或是凍雨后,氣溫降低到了冰點附近,導致濕潤的土壤出現(xiàn)結冰膨脹,土壤的凍脹使測雪板被土壤頂起,導致雪深測量出現(xiàn)錯誤數(shù)據(jù)。另外,在日常的維護或是標定過程中由于操作不當?shù)仍蛞部赡艹霈F(xiàn)錯誤數(shù)據(jù)。
從雪深觀測站的海拔高度、當時的氣溫、濕度條件來人工判斷是否可能有降雪和積雪。最為直觀的方法是通過采集測雪板上的圖像信息直接判斷是否確實有積雪。通過圖像識別技術可自動從測雪板的圖像上識別出是否有積雪現(xiàn)象,提高排查雪深疑誤數(shù)據(jù)效率。
在自然背景條件下通過圖像對測雪板上的圓形測雪點進行積雪自動識別具有一定的難度,照明、陰影遮擋、空氣污染、氣候條件(雨、霧等)都會直接影響到圖像識別的準確性。為確保圖像識別的準確性,可先截取圖像需要識別的區(qū)域,過濾掉大部分無關背景,然后進行顏色過濾,轉(zhuǎn)換為灰度圖像并做圖像平滑處理,減少圖像的噪聲以利于最終結果的檢測。
使用Hough變換方法對預處理的圖像進行邊緣檢測,其原理是利用兩個坐標空間之間的變換將一個空間中具有相同形狀的曲線或直線映射到另一個坐標空間的一個點上形成峰值,從而把檢測任意形狀的問題轉(zhuǎn)化為統(tǒng)計峰值問題。使用Hough變換的優(yōu)點是,檢測到一個圓之后就能得到這個圓的位置和半徑數(shù)據(jù)信息,有了這些數(shù)據(jù)信息就可以用來從測雪板圖像上提取出圓形測雪點的區(qū)域,然后再針對這個圓形區(qū)域進行重點識別。
OpenCV是英特爾公司為實時應用進行優(yōu)化的C/C++計算機視覺庫[1]。它開源、高效、便于移植和擴展,提供多種語言接口,實現(xiàn)了很多圖像處理和計算機視覺的通用算法[2]。在其官方網(wǎng)站opencv.org上可以下載到針對不同操作系統(tǒng)的OpenCV。通過編譯源代碼,生成適合實際生產(chǎn)環(huán)境的庫文件。
3.1 HoughCircles函數(shù)介紹
OpenCV中對圓的檢測方法是HoughCircles函數(shù),該方法就是利用Hough變換梯度算法檢測出灰度圖中的圓。其原函數(shù)為:
void cv::HoughCircles(InputArray _image, OutputArray _circles, int method, double dp, double min_dist, double param1, double param2, int minRadius, int maxRadius)
通常情況下,該函數(shù)檢測圓的中心是有效的。然而,它可能無法找到正確半徑。如果知道待測圓的大概半徑,就可通過半徑范圍設置找到合適的圓。
在實際應用中,要注意參數(shù)的選擇,選擇合適的參數(shù)得到的圓位置和半徑也就越準確。圖1a圖的邊緣檢測閾值25,圖1b圖的邊緣檢測閾值70,圖1c圖的邊緣檢測閾值105。圖2a圖是圖1a的圓檢測結果,圖2b圖是圖1b和圖1c的圓檢測結果。
(a圖的邊緣檢測閾值25、b圖的邊緣檢測閾值70、c圖的邊緣檢測閾值105)圖1 不同邊緣檢測閾值的檢測結果
(a圖是圖1a的圓檢測結果、b圖是圖1b和圖1c的圓檢測結果)圖2 不同邊緣檢測閾值的圓檢測結果
3.2 開發(fā)環(huán)境搭建
開發(fā)環(huán)境的搭建工具下載、編譯器配置、建立解決方案等。
下載OpenCV源代碼和cmake-gui工具,運行cmake-gui.exe,選擇OpenCV源代碼路徑和生成路徑。
配置編譯器,考慮到圖像處理需要大量耗費CPU、GPU和內(nèi)存資源建議選擇Win64。
解決方案生成,點擊Finish按鈕,CMake開始自動配置,配置結束后顯示Configuring done。接著建立解決方案,通過點擊Generate按鈕自動在x64build下建立解決方案。
啟動Visual Studio 2015,打開x64build下的OpenCV解決方案,重新生成解決方案。在解決方案資源管理器中,展開CMakeTarget目錄,右鍵其中的INSTALL工程,選擇“僅用于項目”中的“僅生成INSTALL”,在x64build/install/x64/vc14下就可以看到有很多64位環(huán)境下的OpenCV庫文件。
建立基于.Net Framework 4.0的Windows Forms解決方案,在解決方案中添加所需的OpenCV庫文件。OpenCV有很多強大的功能,本文敘述利用Hough變換來檢測圓形的功能,因此只需要添加opencv_core.dll、opencv_imgproc.dll、opencv_highgui.dll這幾個類庫文件。引入的64位OpenCV類庫,將解決方案生成目標平臺修改為x64。
分辨率、寬度、高度、像素位深度、顏色空間是處理圖像最基本幾個要素。像素位深度、顏色空間很常用,因此將像素位深度和顏色空間轉(zhuǎn)換定義為枚舉類型,如:
public enum IplImageDepth :int {U8=8,…}
public enum ColorConversion :int{...Bgr2Gray=6,Gray2Bgr=8,…}
需要用到OpenCV庫的函數(shù)有下面這些,使用DllImport引入這些函數(shù),并自主擴展成C#的方法:
顏色空間轉(zhuǎn)換代碼:
[DllImport("opencv_imgproc248", CallingConvention=CallingConvention.Cdecl)]
internal static extern void cvCvtColor(ArrayLike src, ArrayLike dst, ColorConversion colorCode);
圖像高斯平滑代碼:
[DllImport("opencv_imgproc248", CallingConvention=CallingConvention.Cdecl)]
internal static extern void cvSmooth(ArrayLike src,ArrayLike dst,SmoothMethod method,int size1,int size2,double sigma1,double sigma2);
圖像邊緣檢測代碼:
[DllImport("opencv_imgproc248", CallingConvention=CallingConvention.Cdecl)]
internal static extern void cvCanny(ArrayLike image, ArrayLike edges, double threshold1, double threshold2, int apertureSize);
Hough變換圓形檢測代碼:
[DllImport("opencv_imgproc248", CallingConvention=CallingConvention.Cdecl)]
internal static extern Seq cvHoughCircles(ArrayLike image, CVHandle circle_storage, HoughCirclesMethod method, double dp, double min_dist, double param1, double param2, int min_radius, int max_radius);
如圖3是一張測雪板實景照片,這張受太陽光影響的圖像出現(xiàn)了明顯的明亮和陰影分界,加大圓檢測的難度。
圖3 測雪板實景原始照片
因此先截取圓形測雪點附近區(qū)域,然后進行圖像平滑處理,為后面的圓檢測排除無關干擾,同時縮小處理范圍以利于節(jié)省系統(tǒng)資源開支。圖像高斯平滑處理關鍵代碼:
private IplImage SmoothImage(IplImage originalImage)
{
IplImage image=originalImage.GetSubRect(new Rect(190, 150, 200, 200));
∥截取測雪點附近200×200像素區(qū)域
Size resolution=image.Size;
IplImage ret=new IplImage(resolution, IplImageDepth.U8, 1);
CvtColor(image, ret, ColorConversion.Bgr2Gray);
int passes=Passes;
∥平滑重復次數(shù),此處的Passes為來自指定參數(shù)配置
int x=XKernel;
∥一般為卷積核的水平方向直徑(選擇高斯平滑時必須為奇數(shù)),此處的Xkernel來自實際應用的指定參數(shù)配置
int y=YKernel;
∥在簡單/非尺度變換的高斯模糊的情況下,如果y的值為零,則表示其被設定為x,此處的YKernel為來自指定參數(shù)配置
for (int i=0; i < passes; i++)
{OpenCV.Smooth(ret, ret, SmoothMethod.Gaussian, x, y, 0, 0); }
return ret;
}
實際平滑后的輸出圖像如圖4。
圖4 高斯平滑處理好的圖像
接著對高斯平滑后的圖像進行邊緣檢測,圖像邊緣檢測的關鍵代碼如下:
IplImage canny=new IplImage(resolution, IplImageDepth.U8, 1);
OpenCV.Canny(smoothResult, canny, Math.Max(cannyThreshold/2, 1), cannyThreshold, 3);
∥其中smoothResult為圖像平滑處理返回的結果,cannyThreshold為來自指定參數(shù)的邊緣檢測閾值
圖5a為對指定區(qū)域進行邊緣檢測的結果,圖5b圖為整幅圖像進行邊緣檢測的結果,在這一步中可以很明顯可以看出,圖5b中的一些無光邊緣會為后面的圓檢測帶來很大的干擾。因此,在這個實際應用中截取指定區(qū)域的圖像顯得尤為重要。
(a)指定區(qū)域的邊緣檢測結果;(b)整幅圖像的邊緣檢測結果圖5 不同區(qū)域的邊緣檢測結果
將OpenCV中的圓檢測C++代碼實現(xiàn)成C#代碼:
public static Seq HoughCircles(ArrayLike image, CVHandle circleStorage, HoughCirclesMethod method, double dp, double minDist, double param1, double param2, int minRadius, int maxRadius)
{
var circles=cvHoughCircles(image, circleStorage, method, dp, minDist, param1, param2, minRadius, maxRadius);
if (circles.IsInvalid) return null;
circles.SetOwnerStorage((MemoryStorage)circleStorage);
return circles;
}
然后就可以在.Net Framework框架下輕松調(diào)用這個函數(shù)檢測圖像中的圓:
public static Seq DetectCircles(IplImage pImage, HoughDetectionSettings pSettings)
{
Seq ret;
try{
MemStorage storage=new MemStorage(0);
ret=OpenCV.HoughCircles(pImage, storage, HoughCirclesMethod.Gradient,dp,minDistance,cannyThreshold,accuThreshold,minRadius,maxRadius);
}catch{throw;}
return ret;
}
最后,把這些圓從原圖中標識出來:
public static void DrawCircles(IplImage pImage, Seq circles)
{
try{
int count=circles.Count;
for (int i=0; i < count; i++)
{
float[] p=new float[3];
Marshal.Copy(pCircles.GetElement(i), p, 0, 3);
CV.Circle(pImage,new Point((int)Math.Round(p[0]), (int)Math.Round(p[1])), 3, new Scalar(0, 255, 0),-1,LineFlags.Connected8, 0);
CV.Circle(pImage, new Point((int)Math.Round(p[0]), (int)Math.Round(p[1])), (int)Math.Round(p[2]), new Scalar(255, 0, 0), 3, LineFlags.Connected8, 0);
}
}catch{throw;}
}
如圖6所示,為最終實際測雪點的圓檢測結果。
圖6 實際的圓檢測結果
有了這個圓形關鍵區(qū)域,一般就可以認為不存在積雪。但是也可能下了薄薄的一層雪卻還保留著這個圓,因此還要進一步對這個圓形區(qū)
域進行色彩識別等。進行色彩識別需要對圖像進行色彩空間轉(zhuǎn)換、二值化處理、膨脹腐蝕處理等[3]。最終明確測雪點上是否覆蓋了雪,從而協(xié)助輔助判斷自動雪深觀測儀當前實時數(shù)據(jù)是否為疑誤數(shù)據(jù)。
隨著自動雪深觀測站和雪深實景監(jiān)控的大量部署,應當充分發(fā)揮雪深實景監(jiān)控的作用從而確保雪深數(shù)據(jù)準確可靠。為了達到這個目的,本文對基于OpenCV實現(xiàn)對測雪點的智能識別的關鍵方法進行了詳細分析,利用OpenCV中的多種圖像處理功能輔助協(xié)助處理雪深觀測站的疑誤數(shù)據(jù)。但現(xiàn)有的圖像處理算法仍有不足之處,在較為復雜的自然環(huán)境下,由于光線、遮擋等復雜情況都會對圖像處理結果產(chǎn)生影響。因此,提高識別的準確率是應用中的難點,需要對OpenCV中算法做進一步研究和擴展。
[1] 于仕琪,劉瑞禎.學習OpenCV(中文版)[M].北京:清華大學出版社,2009.
[2] 方玫,喻擎蒼,李華強,等.C++Builder下基于OpenCV的數(shù)字圖像的處理[J].計算機工程與設計,2008,29(4):882-884.
[3] 劉潔,馮貴玉,張汗靈.一種圖像處理和計算機視覺的開發(fā)工具[J].計算機仿真,2006,23(11):305-307.
2016-03-28