天天看点

opencv图像分割合成_【3】OpenCV图像处理模块(10)inRange函数实现阈值化,HSV图像分割...

opencv图像分割合成_【3】OpenCV图像处理模块(10)inRange函数实现阈值化,HSV图像分割...

本节使用inRange函数来实现阈值化。跟前面的阈值化方法一样,只不过在实现时用阈值范围来替代固定阈值。

本节还提供了一种物体检测的手段,用基于像素值范围的方法,在HSV色彩空间检测物体。

HSV色彩空间

HSV(hue,saturation,value的首字母,分别表示颜色的色相、饱和度、强度)色彩空间是一种类似于RGB的颜色表示方式。hue通道是颜色类型,在需要根据颜色来分割物体的应用中,非常有效。saturation 的变化从不饱和到完全饱和,对应下图中灰色过度到阴影(没有白色成分)。Value描述了颜色的强度或者说亮度。下面是HSV圆柱体,表示HSV的颜色空间。

opencv图像分割合成_【3】OpenCV图像处理模块(10)inRange函数实现阈值化,HSV图像分割...

HSV色彩空间By SharkDderivative work: SharkD [CC BY-SA 3.0 or GFDL], via Wikimedia Commons

由于RGB色彩空间是由三个来编码颜色,所以难以根据颜色来分割物体。

opencv图像分割合成_【3】OpenCV图像处理模块(10)inRange函数实现阈值化,HSV图像分割...

RGB色彩空间By SharkD [GFDL or CC BY-SA 4.0], from Wikimedia Commons

颜色空间的转换可使用cvtColor函数。

代码

// @tutorials imgproc module 10
// @文件 Threshold_inRange.cpp
// @主题 HSV图像的阈值分割,检测目标
// @修改 CVer
// @日期 2019年12月27日
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/videoio.hpp"
#include <iostream>

using namespace cv;

const int max_value_H = 360/2;
const int max_value = 255;
const String window_capture_name = "Video Capture";
const String window_detection_name = "Object Detection";
int low_H = 0, low_S = 0, low_V = 0;
int high_H = max_value_H, high_S = max_value, high_V = max_value;

//下面6个函数分别设置HSV三个通道分量的范围,每个通道最低值和最高值
static void on_low_H_thresh_trackbar(int, void *)
{
    low_H = min(high_H-1, low_H);
    setTrackbarPos("Low H", window_detection_name, low_H);
}

static void on_high_H_thresh_trackbar(int, void *)
{
    high_H = max(high_H, low_H+1);
    setTrackbarPos("High H", window_detection_name, high_H);
}

static void on_low_S_thresh_trackbar(int, void *)
{
    low_S = min(high_S-1, low_S);
    setTrackbarPos("Low S", window_detection_name, low_S);
}

static void on_high_S_thresh_trackbar(int, void *)
{
    high_S = max(high_S, low_S+1);
    setTrackbarPos("High S", window_detection_name, high_S);
}

static void on_low_V_thresh_trackbar(int, void *)
{
    low_V = min(high_V-1, low_V);
    setTrackbarPos("Low V", window_detection_name, low_V);
}

static void on_high_V_thresh_trackbar(int, void *)
{
    high_V = max(high_V, low_V+1);
    setTrackbarPos("High V", window_detection_name, high_V);
}

int main(int argc, char* argv[])
{//这里可以选择打开视频文件或者摄像头
    String videofile = samples::findFile("D:/opencv/sources/doc/js_tutorials/js_assets/cup.mp4");
    VideoCapture cap(videofile);//打开视频文件
    //VideoCapture cap(0);//打开摄像头

    namedWindow(window_capture_name);
    namedWindow(window_detection_name);

    //Trackbar分别设置HSV三个分量大小
    createTrackbar("Low H", window_detection_name, &low_H, max_value_H, on_low_H_thresh_trackbar);
    createTrackbar("High H", window_detection_name, &high_H, max_value_H, on_high_H_thresh_trackbar);
    createTrackbar("Low S", window_detection_name, &low_S, max_value, on_low_S_thresh_trackbar);
    createTrackbar("High S", window_detection_name, &high_S, max_value, on_high_S_thresh_trackbar);
    createTrackbar("Low V", window_detection_name, &low_V, max_value, on_low_V_thresh_trackbar);
    createTrackbar("High V", window_detection_name, &high_V, max_value, on_high_V_thresh_trackbar);

    Mat frame, frame_HSV, frame_threshold;
    while (true)
    {//获取图像帧
        cap >> frame;
        if(frame.empty())
        {
            break;
        }
        // BGR转换到HSV色彩空间
        cvtColor(frame, frame_HSV, COLOR_BGR2HSV);
        // 根据HSV设置的范围,检测目标
        inRange(frame_HSV, Scalar(low_H, low_S, low_V), Scalar(high_H, high_S, high_V), frame_threshold);

        // 显示分割结果
        imshow(window_capture_name, frame);
        imshow(window_detection_name, frame_threshold);

        //按q或esc退出
        char key = (char) waitKey(30);
        if (key == 'q' || key == 27)
        {
            break;
        }
    }
    return 0;
}
           

结果

程序运行后,通过trackbar分别设置HSV像素范围,截取部分处理结果如下图。可以看到设置不同的值,可以得到不同的分割效果。

opencv图像分割合成_【3】OpenCV图像处理模块(10)inRange函数实现阈值化,HSV图像分割...
opencv图像分割合成_【3】OpenCV图像处理模块(10)inRange函数实现阈值化,HSV图像分割...

分割得到手和手臂

opencv图像分割合成_【3】OpenCV图像处理模块(10)inRange函数实现阈值化,HSV图像分割...
opencv图像分割合成_【3】OpenCV图像处理模块(10)inRange函数实现阈值化,HSV图像分割...

分割得到杯子和手臂