c++ 如何在opencv中与RGB颜色进行比较并生成蒙版?

mnemlml8  于 9个月前  发布在  其他
关注(0)|答案(1)|浏览(134)

我想在opencv中匹配一个特定的RGB颜色,并在匹配的地方生成一个蒙版。我尝试使用compare(),但它在三个通道上独立运行。下面是我的测试程序,我希望它能匹配绿色(00ff00),但它根本不能。

cv::Mat testImg = cv::imread("test.png", cv::IMREAD_COLOR);
    cv::Mat mask(testImg.size().height, testImg.size().width, CV_8U, cv::Scalar(0));
    cv::compare(testImg, cv::Vec3b(0x00, 0xff, 0x00), mask, cv::CMP_EQ);
    imwrite("out.png", mask);

字符串
例如,对于下面的输入,我期望代码与第一行中的绿色方块匹配:


的数据
但是输出显示它在逐个通道的基础上匹配0(忽略0xff),所以遮罩最终使用反转的颜色(不是布尔值),这根本不是我想要的:



我可以split通道,运行compare三次,并合并结果,但我希望有一个更好的方法。我可以将3通道图像转换为一个24位通道并一次比较所有24位吗?我应该使用inRange吗?

a7qyws3x

a7qyws3x1#

您可以使用cv::inRange沿着每个颜色的HSV值来创建您要查找的颜色的二进制掩码。一个选项是创建一个颜色名称为stringstd::map< std::string, std::vector<cv::Scalar> >和一个低阈值和高阈值的std::vector。迭代Map并创建掩码。类似于以下内容(对于红色,绿色和蓝色):

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <opencv2/opencv.hpp>

int main()
{

    // Read image:
    std::string imagePath = "D://opencvImages//BkxkG.png";
    cv::Mat inputImage = cv::imread(imagePath, cv::IMREAD_COLOR);

    // Convert BGR image to HSV:
    cv::Mat hsvImage;
    cv::cvtColor(inputImage,hsvImage, cv::COLOR_BGR2HSV);

    // Dictionary of HSV values:
    std::map< std::string, std::vector<cv::Scalar> > colorDict;

    // Green:
    std::vector<cv::Scalar> colorData = { cv::Scalar( 52, 255, 0 ), cv::Scalar( 67, 255, 255 ) };
    colorDict.emplace("Green", colorData);

    // Red:
    colorData = { cv::Scalar( 0, 185, 0 ), cv::Scalar( 10, 255, 255 ) };
    colorDict.emplace("Red", colorData);

    // Blue:
    colorData = { cv::Scalar( 95, 255, 0 ), cv::Scalar( 130, 255, 255 ) };
    colorDict.emplace("Blue", colorData);

    // Loop through the color dictionary:
    std::map< std::string, std::vector<cv::Scalar> >::iterator it;
    for ( it = colorDict.begin(); it != colorDict.end(); it++ ){

        // Get key:
        std::string currentColor = it->first;

        // Get thresholds:
        std::vector<cv::Scalar> currentThresholds = it->second;
        cv::Scalar lowthreshold = currentThresholds[0];
        cv::Scalar highthreshold = currentThresholds[1];

        // Create HSV mask:
        cv::Mat currentMask;
        cv::inRange(hsvImage, lowthreshold, highthreshold, currentMask);

        std::cout<<"Current Mask: "<<currentColor<<std::endl;
        cv::imshow("CurrentMask", currentMask);
        cv::waitKey(0);

        // AND mask and original input:
        cv::Mat currentColorMask;
        cv::bitwise_and(inputImage, inputImage, currentColorMask, currentMask);
        cv::imshow("currentColorMask", currentColorMask);
        cv::waitKey(0);

    }

    return 0;
}

字符串
对于蓝色,你得到这个二进制掩码:


的数据
如果你AND这个遮罩和原始输入图像,你会得到这个:


相关问题