opencv(C++) 學習記錄11.30(顏色識別)


2019-11-30     

這周主要還是在學習opencv基本API的應用與原理,同時也在學習C++的線程,那么這次就記錄對燈條的顏色識別 

  HSV基本顏色分量范圍(通過實驗得到的模糊范圍,實際操作中我們可以據此做出適當調整)      

 

 

 

                                                                                      

#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
#include <math.h>
using namespace cv;
using namespace std;

int main()
{
//VideoCapture cap("D:/H.mp4"); //capture the video from web cam

//if (!cap.isOpened()) // if not success, exit program
//{
// cout << "Cannot open the web cam" << endl;
// return -1;
//}

namedWindow("control", 1);
int ctrl = 0;
createTrackbar("ctrl", "control", &ctrl, 7);

while (true)
{
Mat imgOriginal;

//bool bSuccess = cap.read(imgOriginal); 
//if (!bSuccess) 
//{
// cout << "Cannot read a frame from video stream" << endl;
// break;
//}

imgOriginal = imread("D:/L.png");

Mat imgHSV, imgBGR;
Mat imgThresholded;

if (0)
{
vector<Mat> hsvSplit; //創建向量容器,存放HSV的三通道數據
cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV
split(imgHSV, hsvSplit); //分類原圖像的HSV三通道
equalizeHist(hsvSplit[2], hsvSplit[2]); //對HSV的亮度通道進行直方圖均衡
merge(hsvSplit, imgHSV);//合並三種通道
cvtColor(imgHSV, imgBGR, COLOR_HSV2BGR); //將HSV空間轉回至RGB空間,為接下來的顏色識別做准備
}
else
{
imgBGR = imgOriginal.clone();
}

 

switch (ctrl)
{
case 0:
{
inRange(imgBGR, Scalar(60, 120, 245), Scalar(120, 255, 255), imgThresholded); //藍色
break;
}
case 1:
{
inRange(imgBGR, Scalar(128, 128, 128), Scalar(255, 255, 255), imgThresholded); //白色
break;
}
case 2:
{
inRange(imgBGR, Scalar(128, 128, 0), Scalar(255, 255, 127), imgThresholded); //靛色
break;
}
case 3:
{
inRange(imgBGR, Scalar(128, 0, 128), Scalar(255, 127, 255), imgThresholded); //紫色
break;
}
case 4:
{
inRange(imgBGR, Scalar(0, 128, 128), Scalar(127, 255, 255), imgThresholded); //黃色
break;
}
case 5:
{
inRange(imgBGR, Scalar(0, 128, 0), Scalar(127, 255, 127), imgThresholded); //綠色
break;
}
case 6:
{
inRange(imgBGR, Scalar(0, 0, 128), Scalar(127, 127, 255), imgThresholded); //紅色
break;
}
case 7:
{
inRange(imgBGR, Scalar(0, 0, 0), Scalar(127, 127, 127), imgThresholded); //黑色
break;
}
}

imshow("形態學去噪聲前", imgThresholded);

Mat element = getStructuringElement(MORPH_RECT, Size(10, 15));
morphologyEx(imgThresholded, imgThresholded, MORPH_OPEN, element);
morphologyEx(imgThresholded, imgThresholded, MORPH_CLOSE, element);

imshow("Thresholded Image", imgThresholded); //show the thresholded image
imshow("直方圖均衡以后", imgBGR);
imshow("Original", imgOriginal); //show the original image

char key = (char)waitKey(300);
if (key == 27)
break;
}

return 0;

}

                       

 

 

通過滑條發現ctrl=1 時 效果較好,但數字沒有消除。

當我單獨分出藍色識別范圍,並繼續用HSV空間時。

#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
#include <math.h>
using namespace cv;
using namespace std;

int main()
{
    //VideoCapture cap("D:/H.mp4"); //if (!cap.isOpened()) //{
    //    cout << "Cannot open the web cam" << endl;
    //    return -1;
    //}

    namedWindow("control", 1);
    int ctrl = 0;
    createTrackbar("ctrl", "control", &ctrl, 7);

    while (true)
    {
        Mat imgOriginal;

        //bool bSuccess = cap.read(imgOriginal); //if (!bSuccess) //if not success, break loop
        //{
        //    cout << "Cannot read a frame from video stream" << endl;
        //    break;
        //}

        imgOriginal = imread("D:/L.png");

        Mat imgHSV, imgBGR;
        Mat imgThresholded;

        if (imgOriginal.empty())
        {
            cout << "open failed" << endl;
            return -1;
        }
        /*else
        {
            imgBGR = imgOriginal.clone();
        }
*/
            vector<Mat> hsvSplit; //創建向量容器,存放HSV的三通道數據
            cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); 
            split(imgHSV, hsvSplit);    //分類原圖像的HSV三通道
            equalizeHist(hsvSplit[2], hsvSplit[2]); //對HSV的亮度通道進行直方圖均衡
            merge(hsvSplit, imgBGR);//合並三種通道
            //cvtColor(imgHSV, imgBGR, COLOR_HSV2BGR); //將HSV空間轉回至RGB空間,為接下來的顏色識別做准備

        switch (ctrl)
        {
        case 0:
        {
            inRange(imgBGR, Scalar(60, 120, 245), Scalar(120, 255, 255), imgThresholded); //藍色
            break;
        }
        case 1:
        {
            inRange(imgBGR, Scalar(128, 128, 128), Scalar(255, 255, 255), imgThresholded); //白色
            break;
        }
        case 2:
        {
            inRange(imgBGR, Scalar(128, 128, 0), Scalar(255, 255, 127), imgThresholded); //靛色
            break;
        }
        case 3:
        {
            inRange(imgBGR, Scalar(128, 0, 128), Scalar(255, 127, 255), imgThresholded); //紫色
            break;
        }
        case 4:
        {
            inRange(imgBGR, Scalar(0, 128, 128), Scalar(127, 255, 255), imgThresholded); //黃色
            break;
        }
        case 5:
        {
            inRange(imgBGR, Scalar(0, 128, 0), Scalar(127, 255, 127), imgThresholded); //綠色
            break;
        }
        case 6:
        {
            inRange(imgBGR, Scalar(0, 0, 128), Scalar(127, 127, 255), imgThresholded); //紅色
            break;
        }
        case 7:
        {
            inRange(imgBGR, Scalar(0, 0, 0), Scalar(127, 127, 127), imgThresholded); //黑色
            break;
        }
        }

        imshow("形態學去噪聲前", imgThresholded);

        Mat element = getStructuringElement(MORPH_RECT, Size(10, 15));
        morphologyEx(imgThresholded, imgThresholded, MORPH_OPEN, element);
        morphologyEx(imgThresholded, imgThresholded, MORPH_CLOSE, element);

        imshow("Thresholded Image", imgThresholded); //show the thresholded image
        imshow("直方圖均衡以后", imgBGR);
        imshow("Original", imgOriginal); //show the original image

        char key = (char)waitKey(300);
        if (key == 27)
            break;
    }

    return 0;

}

 

 效果如下

 

 

 

通過代碼對比發現如果將HSV再轉換位BGR空間的時候,HSV的顏色將不適用,因此做好圖像的預處理是非常重要。這對於圖像轉換為視頻有着必然的聯系。

總結一下部分API功能及代碼講解。

 

 

 

 

InRange
檢查數組元素是否在兩個數組之間
void cvInRange( const CvArr* src, const CvArr* lower, const CvArr* upper, CvArr*
dst );
src
第一個原數組
lower
包括進的下邊界數組
upper
不包括進的上邊界線數組
dst
輸出數組必須是 8u 或 8s 類型.
函數 cvInRange 對輸入的數組作范圍檢查:
dst(I)=lower(I)0 <= src(I)0 < upper(I)0
對於單通道數組:
dst(I)=lower(I)0 <= src(I)0 < upper(I)0 &&
lower(I)1 <= src(I)1 < upper(I)1
對二通道數組,以此類推
如果 src(I) 在范圍內 dst(I)被設置為 0xff (每一位都是 '1')否則置 0 。 除了輸出
數組所有數組必須是相同的類型相同的大小(或 ROI 大小)。 
 
 
Split
分割多通道數組成幾個單通道數組或者從數組中提取一個通道
void cvSplit( const CvArr* src, CvArr* dst0, CvArr* dst1,
CvArr* dst2, CvArr* dst3 );
#define cvCvtPixToPlane cvSplit
src
原數組.
dst0...dst3
目標通道
函數 cvSplit 分割多通道數組成分離的單通道數組 d。可獲得兩種操作模式 . 如果原
數組有 N 通道且前 N 輸出數組非 NULL, 所有的通道都會被從原數組中提取,如果前 N
個通道只有一個通道非 NULL 函數只提取該指定通道,否則會產生一個錯誤,余下的通
道(超過前 N 個通道的以上的)必須被設置成 NULL,對於設置了 COI 的 IplImage 結使
用 cvCopy 也可以從圖像中提取單通道。 

 

Merge
從幾個單通道數組組合多通道數組或插入一個單通到數組
void cvMerge( const CvArr* src0, const CvArr* src1,
const CvArr* src2, const CvArr* src3, CvArr* dst );
#define cvCvtPlaneToPix cvMerge
src0... src3
輸入的通道.
dst
輸出數組.
函數 cvMerge 是前一個函數的反向操作。如果輸出數組有 N 個通道並且前 N 個輸入通道
非 NULL,就拷貝所有通道到輸出數組,如果在前 N 個通道中只有一個單通道非 NULL ,
只拷貝這個通道到輸出數組,否則 就會產生錯誤。除前 N 通道以外的余下的通道必須
置 NULL。對於設置了 COI 的 IplImage 結構使用 cvCopy 也可以實現向圖像中插入一個
通道 。 

 總之這周學習的東西也有不少,但沒有整理好,因為快考試也在忙着復習功課,時間上特別的緊。后面我將繼續學習下裝甲板的識別。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM