检测红色圆圈| openCV | Java的

时间:2017-05-27 16:32:32

标签: java opencv geometry detection color-detection

我正在编写一个程序,需要从这张图片中检测出红色圆圈。

enter image description here

我尝试过canny边缘检测并找到轮廓,但没有人发现这个红色的“圆圈”。我也尝试将其转换为hsv并通过颜色检测,但我无法确定这种颜色的良好范围,也许背景颜色混淆了它?

我在最后的尝试中放了一段我的代码..

Mat image = new Mat();
image = Imgcodecs.imread("image.jpg");
Mat hsvImage = new Mat();
Mat grayscaleImage = new Mat();
Mat binaryImage = new Mat();
Imgproc.blur(image, image, new Size(1, 1));  
Imgproc.cvtColor(image, hsvImage, Imgproc.COLOR_BGR2HSV);           
Imgproc.cvtColor(image, grayscaleImage, Imgproc.COLOR_BGR2GRAY);            
Imgproc.equalizeHist(grayscaleImage, grayscaleImage);
Imgproc.Canny(grayscaleImage, grayscaleImage, 50, 150, 3,false);

List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
        Imgproc.findContours(grayscaleImage.clone(), contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);


        for (int id=0;id<contours.size();id++){
            MatOfPoint2f mop2f = new MatOfPoint2f();
            contours.get(id).convertTo(mop2f,CvType.CV_32F);
            RotatedRect rectangle = Imgproc.minAreaRect(mop2f);
            if (rectangle.boundingRect().width>80)
            Imgproc.drawContours(image,contours,id,new Scalar(0,255,0));

        }

2 个答案:

答案 0 :(得分:3)

如果您想处理标记的图像,您可能真的想要检测颜色。通常这是在HSV颜色空间中完成的。

这是一些用于检测&#34; red&#34;的C ++代码。颜色。结果还不足以使用findContours,但可能在一些扩张之后。也许你可以将代码转换为Java。

如果要检测不同的颜色,请将行redMask = thresholdHue(hsv, 0, 20, 50, 50);更改为mask = thresholdHue(hsv,yourWantedHueColorValue,20,50,50);`

// for example to shift a circluar hue-channel
cv::Mat shiftChannel(cv::Mat H, int shift, int maxVal = 180)
{
    // CV_8UC1 only!
    cv::Mat shiftedH = H.clone();
    //int shift = 25; // in openCV hue values go from 0 to 180 (so have to be doubled to get to 0 .. 360) because of byte range from 0 to 255
    for (int j = 0; j < shiftedH.rows; ++j)
    for (int i = 0; i < shiftedH.cols; ++i)
    {
        shiftedH.at<unsigned char>(j, i) = (shiftedH.at<unsigned char>(j, i) + shift) % maxVal;
    }

    return shiftedH;
}

cv::Mat thresholdHue(cv::Mat hsvImage, int hueVal, int range = 30, int minSat = 50, int minValue = 50)
{
    // hsvImage must be CV_8UC3 HSV image.
    // hue val and range are in openCV's hue range (0 .. 180)
    // range shouldnt be bigger than 90, because that's max (all colors), after shifting the hue channel.

    // this function will
    //    1. shift the hue channel, so that even colors near the border (red color!) will be detectable with same code.
    //    2. threshold the hue channel around the value 90 +/- range

    cv::Mat mask; // return-value

    std::vector<cv::Mat> channels;
    cv::split(hsvImage, channels);

    int targetHueVal = 180 / 2; // we'll shift the hue-space so that the target val will always be 90 afterwards, no matter which hue value was chosen. This can be important if 
    int shift = targetHueVal - hueVal;
    if (shift < 0) shift += 180;

    cv::Mat shiftedHue = shiftChannel(channels[0], shift, 180);

    // merge the channels back to hsv image
    std::vector<cv::Mat> newChannels;
    newChannels.push_back(shiftedHue);
    newChannels.push_back(channels[1]);
    newChannels.push_back(channels[2]);
    cv::Mat shiftedHSV;
    cv::merge(newChannels, shiftedHSV);

    // threshold
    cv::inRange(shiftedHSV, cv::Vec3b(targetHueVal - range, minSat, minValue), cv::Vec3b(targetHueVal + range, 255, 255), mask);

    return mask;
}


int main(int argc, char* argv[])
{
    cv::Mat input = cv::imread("C:/StackOverflow/Input/redCircleLikeContours.jpg");


    cv::Mat redMask; 

    cv::Mat hsv;
    cv::cvtColor(input, hsv, CV_BGR2HSV);

    redMask = thresholdHue(hsv, 0, 20, 50, 50);

    cv::imshow("red", redMask);

    cv::imshow("input", input);
    cv::imwrite("C:/StackOverflow/Output/redCircleLikeContoursMask.png", redMask);

    cv::waitKey(0);
    return 0;
}

结果如下:

enter image description here

答案 1 :(得分:1)

这是我的代码,如果有人想看:)

public static void main (String args[]){

        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);               

        Mat image = new Mat();
        image = Imgcodecs.imread("imageorg.jpg");

        if ( image == null) System.out.println("Image is fine");
        else System.out.println("Wrong path to image");


        Mat hsvImage = new Mat();
        Imgproc.blur(image, image, new Size(3,3));  
        Imgproc.cvtColor(image, hsvImage, Imgproc.COLOR_BGR2HSV);           

        Mat redMask = new Mat();
        redMask = thresholdHue(hsvImage,0,20,50,50);

        Mat kernel = new Mat();
        kernel = Imgproc.getStructuringElement(Imgproc.MORPH_DILATE, new Size(2,2));        

        Mat dilateMat = new Mat();
        Imgproc.dilate(redMask, dilateMat, kernel);                         

        Imgcodecs.imwrite("redCircleLikeContours.png", redMask);                


        List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
        Imgproc.findContours(dilateMat.clone(), contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);           


        List<MatOfPoint> removedContoursList = new ArrayList<MatOfPoint>();         

        for (int id=0;id<contours.size();id++){                     
            MatOfPoint2f mop2f = new MatOfPoint2f();
            contours.get(id).convertTo(mop2f,CvType.CV_32F);
            RotatedRect rectangle = Imgproc.minAreaRect(mop2f);
            if (rectangle.boundingRect().height<10){
                removedContoursList.add(contours.get(id));
                System.out.println("removing: "+rectangle.boundingRect());
                contours.remove(id);
                id--;
            }
        }

    }


    public static Mat thresholdHue(Mat hsvImage, int hueVal, int range, int minSat, int minValue)
    {   
        Mat mask = new Mat(); 

        List<Mat> channels = new ArrayList<Mat>();
        Core.split(hsvImage, channels);

        int targetHueVal = 180 / 2; 
        int shift = targetHueVal - hueVal;
        if (shift < 0) shift += 180;

        Mat shiftedHue = shiftChannel(channels.get(0), shift, 180);


        List<Mat> newChannels = new ArrayList<Mat>();

        newChannels.add(shiftedHue);
        newChannels.add(channels.get(1));
        newChannels.add(channels.get(2));
        Mat shiftedHSV = new Mat();
        Core.merge(newChannels, shiftedHSV);


        Core.inRange(shiftedHSV, new Scalar(targetHueVal - range, minSat, minValue), new Scalar(targetHueVal + range, 255, 255), mask);

        return mask;
    }


    private static Mat shiftChannel(Mat H, int shift, int maxVal)
    {

        Mat shiftedH = H.clone();
        for (int j = 0; j < shiftedH.rows(); ++j)
        for (int i = 0; i < shiftedH.cols(); ++i)
        {
            shiftedH.put(j, i,(shiftedH.get(j,i)[0] + shift) % maxVal);
        }

        return shiftedH;
    }