OpenCV使用顏色進行膚色檢測

語言: CN / TW / HK

theme: hydrogen

持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第18天,點選檢視活動詳情

前言

顏色資訊對於特定物件的初始檢測非常有用。例如,輔助駕駛應用程式中的道路標誌檢測可以依靠標準標誌的顏色來快速提取潛在的候選道路標誌。面板顏色的檢測是另一個例子,其中檢測到的面板區域可以用作影象中是否有人的指標;這種方法經常用於手勢識別,使用膚色檢測來檢測手部位置。

使用顏色進行膚色檢測

通常,要使用顏色進行物件檢測,首先需要收集包含從不同環境條件獲取的物件的大型影象樣本資料庫。需要使用這些影象樣本定義分類器引數,並用於分類的顏色表示。對於膚色檢測,研究表明,來自不同種族的膚色在色調飽和度空間中能夠很好地聚集。出於以上原因,我們將使用色調和飽和度值來識別下圖中的膚色:

F8.png

因此,我們定義一個函式 detectHScolor,該函式基於值的區間(最小和最大色調,以及最小和最大飽和度值)將影象的畫素分類為面板或非面板: cpp void detectHScolor(const cv::Mat& image,    // 輸入影象             double minHue, double maxHue,   // Hue 區間             double minSat, double maxSat,   // Saturation 區間             cv::Mat& mask) {                // 輸出掩碼     // 轉換色彩空間     cv::Mat hsv;     cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV);     // 分割影象通道     std::vector<cv::Mat> channels;     cv::split(hsv, channels);     cv::Mat mask1;     cv::threshold(channels[0], mask1, maxHue, 255, cv::THRESH_BINARY_INV);     cv::Mat mask2;     cv::threshold(channels[0], mask2, minHue, 255, cv::THRESH_BINARY);     cv::Mat hueMask;     if (minHue < maxHue) hueMask = mask1 & mask2;     else hueMask = mask1 | mask2;     cv::threshold(channels[1], mask1, maxSat, 255, cv::THRESH_BINARY_INV);     cv::threshold(channels[1], mask2, minSat, 255, cv::THRESH_BINARY);     cv::Mat satMask;     satMask = mask1 & mask2;     // 組合掩碼     mask = hueMask & satMask; } 有大量包含面板(和非面板)的影象樣本可供使用,我們可以使用概率方法來確定在面板類中觀察給定顏色的可能性與在非面板類中觀察到相同顏色的可能性。在本節中,我們根據經驗為測試影象定義了一個可接受的色調飽和度間區間( 8 位版本的色調從 0180,飽和度從 0255 ): cpp detectHScolor(image, 140, 10, 20, 166, mask); cv::Mat detected(image.size(), CV_8UC3, cv::Scalar(0, 0, 0)); image.copyTo(detected, mask); 執行以上程式,結果得到如下檢測影象:

F9.png

為簡單起見,我們沒有在檢測中考慮顏色飽和度。實際上,排除具有高飽和度的顏色會降低將亮紅色錯誤檢測為面板的可能性。顯然,可靠且準確的膚色檢測需要基於對大量面板樣本更加精細的分析。僅使用色調資訊很難保證對不同影象的均具有良好的檢測效果,因為有許多因素會影響攝影中的色彩效果,例如白平衡和照明條件。儘管如此,僅使用色調資訊作為初始檢測器也可以得到在可接受範圍內的結果。