本文介绍了红色镶边交通标志的颜色阈值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想检测所有红色镶边交通标志(三角形和圆形)。该算法在现实世界中必须高效且稳健,因此我决定使用HSV空间,因为它是光不变的。



我遇到了这个





有人能为我提供正确的价值吗?

解决方案

关键错误恰好在开头:

  Mat rgb = Highgui.imread(scene,Highgui.CV_LOAD_IMAGE_COLOR ); 
Imgproc.cvtColor(rgb,hsv,Imgproc.COLOR_RGB2HSV);

OpenCV C ++ API参考通常是最完整和最详细的,因此引用它绝对不会受到伤害。如果你看一下



如果我们在原始图像上使用此遮罩,我们可以看到我们确实得到了红色位:




I want to detect all red color rimmed traffic signs (Triangular and Circular). The algorithm has to be efficient and robust to work in real world situations, so i decided to use HSV space since it is light invariant.

I came across this question of detecting red objects and the answer was to use this value ranges for HSV: The code is in C++:

inRange(hsv, Scalar(0, 70, 50), Scalar(10, 255, 255), mask1);
inRange(hsv, Scalar(170, 70, 50), Scalar(180, 255, 255), mask2);

Mat1b mask = mask1 | mask2;

Since I am using Java's OpenCV I tried that, but I found out it is not possible to do a Bitwise OR Operation.

So I tried to implement it manually instead of using OpenCV. I also tried same red color value ranges that is provided and sadly the results were horrible:

Here is my code

Mat hsv = new Mat();
Mat rgb = Highgui.imread(scene, Highgui.CV_LOAD_IMAGE_COLOR);
Imgproc.cvtColor(rgb, hsv, Imgproc.COLOR_RGB2HSV);
Mat thresh = new Mat(hsv.size(), CvType.CV_8UC1);


for(int x=0;x<hsv.rows();x++){
    for(int y=0;y<hsv.cols();y++)
    {
        double[] data = hsv.get(x,y);

        double H = data[0];
        double S = data[1];
        double V = data[2];
        if((( 0.0>=H && H<=10.0) && (70.0>=S && S<=255.0) && (50.0>=V && V<=255.0)) || (( 170.0>=H && H<=180.0) && (70.0>=S && S<=255.0) && (50.0>=V && V<=255.0)) ) {

            thresh.put(x,y, 255);
        }
        else
        {
            thresh.put(x,y, 0);
        }
    }
}

Here is the results before and after thresholding

Can someone provide me with right values?

解决方案

The crucial mistake is right in the beginning:

Mat rgb = Highgui.imread(scene, Highgui.CV_LOAD_IMAGE_COLOR);
Imgproc.cvtColor(rgb, hsv, Imgproc.COLOR_RGB2HSV);

The OpenCV C++ API reference is generally the most complete and detailed, so it never hurts to refer to it. If you look at cv::imread you will notice the following note:

However, in your code you treat the image as RGB, i.e. swapping blue and red. This is fatal for your algorithm -- you're looking for red things, but anything that was red is actually blue.

The fix is simple -- rename rgb to bgr (to avoid misleading variable names) and change the conversion code to Imgproc.COLOR_BGR2HSV.

I believe your earlier problems with bitwise_or were just another symptom of this mistake. (I don't really see a reason why it wouldn't work).

See the following example (using OpenCV 3.4.0):

import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.core.Core;

public class test
{
    public static void main(String[] args)
    {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        Mat image = Imgcodecs.imread("test.jpg", Imgcodecs.CV_LOAD_IMAGE_COLOR);
        if ((image == null) || image.empty()) {
            System.out.println("Failed to load input image.");
            System.exit(-1);
        }

        Mat image_hsv = new Mat();
        Imgproc.cvtColor(image, image_hsv, Imgproc.COLOR_BGR2HSV);

        Mat mask1 = new Mat();
        Mat mask2 = new Mat();
        Core.inRange(image_hsv, new Scalar(0, 70, 50), new Scalar(10, 255, 255), mask1);
        Core.inRange(image_hsv, new Scalar(170, 70, 50), new Scalar(180, 255, 255), mask2);

        Mat mask_combined = new Mat();
        Core.bitwise_or(mask1, mask2, mask_combined);

        Mat image_masked = new Mat();
        Core.bitwise_and(image, image, image_masked, mask_combined);

        Imgcodecs.imwrite("test-mask.jpg", mask_combined);        
        Imgcodecs.imwrite("test-masked.jpg", image_masked);

        System.out.println("Done!");
    }
}

Which produces the following combined mask from your sample input image:

If we use this mask on the original image, we can see we really do get the red bits:

这篇关于红色镶边交通标志的颜色阈值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-21 00:41