用色彩空間做圖像處理,讓顏色提取更高效 [利用顏色來分割影像] [OPENCV 水果 識別]
用色彩空間做圖像處理,讓顏色提取更高效 [利用顏色來分割影像] [OPENCV 水果 識別]
資料來源:https://zhuanlan.zhihu.com/p/32269942
https://blog.csdn.net/guduruyu/article/details/70837779
https://tw.saowen.com/a/35b26953aa2e20aefdc8b40b7930b089d19f1c7ab206d3fd988267788e9433fd
01.原彩色圖像:RGB
使用 OpenCV 的 Split 函數,對它進行分離通道的操作,把它分別變成三張單通道的圖片
int main() { cv::Mat src = imread("lenna.jpg", cv::IMREAD_COLOR); cv::imshow("src", src); // Split the image into different channels std::vector<cv::Mat> rgbChannels(3); split(src, rgbChannels); // Show individual channels cv::Mat blank_ch, fin_img; blank_ch = cv::Mat::zeros(cv::Size(src.cols, src.rows), CV_8UC1); // Showing Red Channel // G and B channels are kept as zero matrix for visual perception std::vector<cv::Mat> channels_r; channels_r.push_back(blank_ch); channels_r.push_back(blank_ch); channels_r.push_back(rgbChannels[2]); /// Merge the three channels cv::merge(channels_r, fin_img); cv::imshow("R", fin_img); // Showing Green Channel std::vector<cv::Mat> channels_g; channels_g.push_back(blank_ch); channels_g.push_back(rgbChannels[1]); channels_g.push_back(blank_ch); cv::merge(channels_g, fin_img); cv::imshow("G", fin_img); // Showing Blue Channel std::vector<cv::Mat> channels_b; channels_b.push_back(rgbChannels[0]); channels_b.push_back(blank_ch); channels_b.push_back(blank_ch); cv::merge(channels_b, fin_img); cv::imshow("B", fin_img); cv::waitKey(0); return 0; }
02.灰階(0~255):單通道的圖像是灰色的,每個像素只有一個數字,數字越高,顏色越白,也就越亮。
03.HSV 色彩空間 ~ 在 HSV 色彩空間中 H,S,V 這三個通道分別代表着色相(Hue),飽和度(Saturation)和明度(Value)。
透過HSV可以正確抓出顏色範圍降低光源影響,使用inrange取出特定顏色區塊
int hmax = 360; int hmax_Max = 360; //飽和度 int smin = 0; int smin_Max = 255; int smax = 255; int smax_Max = 255; //亮度 int vmin = 106; int vmin_Max = 255; int vmax = 250; int vmax_Max = 255; //顯示原圖的視窗 string windowName = "src"; //輸出影象的顯示視窗 string dstName = "dst"; //輸出影象 Mat dst; //回撥函式 void callBack(int, void*) { //輸出影象分配記憶體 dst = Mat::zeros(img.size(), CV_32FC3); //掩碼 Mat mask; inRange(hsv, Scalar(hmin, smin / float(smin_Max), vmin / float(vmin_Max)), Scalar(hmax, smax / float(smax_Max), vmax / float(vmax_Max)), mask); //只保留 for (int r = 0; r < bgr.rows; r++) { for (int c = 0; c < bgr.cols; c++) { if (mask.at<uchar>(r, c) == 255) { dst.at<Vec3f>(r, c) = bgr.at<Vec3f>(r, c); } } } //輸出影象 imshow(dstName, dst); //儲存影象 dst.convertTo(dst, CV_8UC3, 255.0, 0); imwrite("HSV_inRange.jpg", dst); } void test_main() { //輸入影象 img = imread("E:\\素材圖片\\1.png",1); if (!img.data || img.channels() != 3) return ; imshow(windowName, img); //彩色影象的灰度值歸一化 img.convertTo(bgr, CV_32FC3, 1.0 / 255, 0); //顏色空間轉換 cvtColor(bgr, hsv, COLOR_BGR2HSV); //定義輸出影象的顯示視窗 namedWindow(dstName, WINDOW_NORMAL); //調節色相 H createTrackbar("hmin", dstName, &hmin, hmin_Max, callBack); createTrackbar("hmax", dstName, &hmax, hmax_Max, callBack); //調節飽和度 S createTrackbar("smin", dstName, &smin, smin_Max, callBack); createTrackbar("smax", dstName, &smax, smax_Max, callBack); //調節亮度 V createTrackbar("vmin", dstName, &vmin, vmin_Max, callBack); createTrackbar("vmax", dstName, &vmax, vmax_Max, callBack); callBack(0, 0); waitKey(0); return; }
04.YUV 色彩空間
YUV 色彩空間實際上是把一幅彩色的圖片分成了一個表示暗亮程度的亮度信號(Luminance)Y,和兩個表示顏色的色度信號(Chrominance)U 和 V。U,V通道分別是藍色通道和紅色通道,Y 通道表示亮度信息。
U 通道數值越高,顏色就越接近藍色,V 通道數值越高,顏色就越接近紅色,Y 通道數值越高,圖片則越亮。
為什么會有這種顏色通道呢?其實這是被歐洲的電視系統釆用的一種顏色編碼方式,主要是為了讓信號支持新的彩色電視,但也繼續支持黑白電視。如果是黑白電視,只使用 Y 通道信號就足夠了。
YUV 的計算相對簡單,圖像處理的速度很快,而且 YUV 格式對於紅、藍色都有很好的識別效果,即使光線變化,算法也可以比較穩定。所以戶外的水果釆摘機器人,一般都釆用了該色彩空間來識別紅藍果實。
有時,你可能會看到 YCbCr,YPbPr 等類似的名詞,其實它們都可以被稱為 YUV,區別只是適用於不同的顯示設備。在計算機上適用的一種 YUV 類型是 YCbCr,同樣 Cb 指藍色色度,Cr 指紅色色度。
2 thoughts on “用色彩空間做圖像處理,讓顏色提取更高效 [利用顏色來分割影像] [OPENCV 水果 識別]”
OPENCV
顏色
色彩
分割
定位
偵測
檢測
色彩空間
應用轉換
圖像去背
顏色偵測