2015-09-26 6 views
4

У меня проблема с обнаружением дорожных знаков скорости с opencv 2.4 для Android. я сделать следующее:Обнаружение дорожного знака с открытым кодом OpenCV

«захвата кадров -> преобразовать его в HSV -> извлечь красные области -> обнаружить признаки с эллипсом обнаружения»

Пока Эллипс обнаружения отлично работает до тех пор, как изображение хорошего качества. Но, как вы видите на рисунках ниже, красное извлечение не работает нормально, из-за низкого качества кадров, по моему мнению.

Преобразование исходного изображения в HSV:

Imgproc.cvtColor(this.source, this.source, Imgproc.COLOR_RGB2HSV, 3); 

Распаковка красных цветов:

Core.inRange(this.source, new Scalar(this.h,this.s,this.v), new Scalar(230,180,180), this.source); 

Так что мой вопрос есть еще один способ обнаружения дорожного знака, как это или извлечения красные области из него, которые, кстати, могут быть очень слабыми, как на последнем снимке?

Это исходное изображение:

enter image description here

Это превращается в HSV, как вы можете видеть красные области выглядят так же, как цвет близлежащих деревьев. Вот как я должен знать, что он красный, но я не могу.

Преобразованные ВПГ:

enter image description here

Это с красными цветами, экстрагированных. Если цвета будут правильными, я должен получить почти идеальный круг/эллипс вокруг знака, но он неполный из-за ложных цветов.

Результат после экстракции:

enter image description here

Эллипс метод:

private void findEllipses(Mat input){ 
Mat thresholdOutput = new Mat(); 
int thresh = 150; 

List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); 
MatOfInt4 hierarchy = new MatOfInt4(); 

Imgproc.threshold(source, thresholdOutput, thresh, 255, Imgproc.THRESH_BINARY); 
//Imgproc.Canny(source, thresholdOutput, 50, 180); 
Imgproc.findContours(source, contours, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); 
RotatedRect minEllipse[] = new RotatedRect[contours.size()]; 

for(int i=0; i<contours.size();i++){ 
    MatOfPoint2f temp=new MatOfPoint2f(contours.get(i).toArray()); 

    if(temp.size().height > minEllipseSize && temp.size().height < maxEllipseSize){ 
     double a = Imgproc.fitEllipse(temp).size.height; 
     double b = Imgproc.fitEllipse(temp).size.width; 
     if(Math.abs(a - b) < 10) 
      minEllipse[i] = Imgproc.fitEllipse(temp); 
    } 
} 
detectedObjects.clear(); 
for(int i = 0; i< contours.size(); i++){ 
    Scalar color = new Scalar(180, 255, 180); 
    if(minEllipse[i] != null){ 
     detectedObjects.add(new DetectedObject(minEllipse[i].center)); 
     DetectedObject detectedObj = new DetectedObject(minEllipse[i].center); 
     Core.ellipse(source, minEllipse[i], color, 2, 8); 
    } 
} 

}

Проблематичный знак: enter image description here

+0

Можете ли вы загрузить оригинальное изображение (RGB)? – Micka

+0

http://picpaste.com/pics/image_5687132_1-85AZtEAd.1443302432.jpg – skyhawk

+0

soryy Могу только опубликовать 2 ссылки раньше – skyhawk

ответ

8

обнаружение дорожных знаков методы here и here.

Вы увидите, что есть 2 способа вы можете достичь этого:

  1. цвета на основе (как то, что вы делаете сейчас)
  2. Shape на основе

В моей опыт, я обнаружил, что методы на основе формы работают очень хорошо, потому что цвет может сильно измениться при различных условиях освещения, качестве камеры и т. д.

Поскольку вам необходимо определить скорость дорожные знаки, которые, как я полагаю, всегда круговые, вы можете использовать детектор эллипса для поиска всех круговых объектов на вашем изображении, а затем применить некоторую проверку, чтобы определить, является ли это дорожным знаком или нет.

Почему обнаружение эллипса?

Ну, так как вы ищете перспективные искаженные круги, вы на самом деле ищете эллипсы. Обнаружение эллипсов в режиме реального времени является интересной (хотя и ограниченной) темой исследования. Я укажу вам на 2 работах с C++ исходный код (который вы можете использовать в вас приложение через родной JNI звонки):

  1. Л. Libuda, И. Grothues, K.-F. Kraiss, обнаружение эллипса в цифровом изображении данные с использованием геометрических признаков, в: J. Braz, A. Ranchordas, H. Arajo, J. Jorge (Eds.), Advances in Computer Graphics and Computer Vision, том 4 Сообщения в Компьютер и информатика, Springer Berlin Heidelberg, 2007, стр. 229-239. link, code

  2. М. Fornaciari, А. Прати, Р. Cucchiara, "Быстрый и эффективный детектор Эллипс для встраиваемых приложений видения", Pattern Recognition, 2014 link, code


ОБНОВЛЕНИЕ

Я пробовал метод 2) без предварительной обработки. Вы можете видеть, что, по крайней мере знаком с красной каймой обнаруживается очень хорошо:

enter image description here

+0

Я понимаю, что означает u, но у меня уже есть обнаружение эллипса, которое не работает само по себе, потому что вокруг слишком много другого. Он обычно обнаруживает что-либо, кроме дорожного знака. Вот почему я хочу изолировать «красные» дорожные знаки, а затем обнаруживать их с помощью эллипса. – skyhawk

+0

Такая же проблема, которая приводит к тому, что цвет не выглядит достаточно разным, вызывает неэффективное обнаружение эллипса. – skyhawk

+0

И, кроме того, мне также понадобится распознавание на основе цвета, потому что круглые знаки движения - это всего лишь начало ... – skyhawk

1
private void findEllipses(Mat input){ 
    Mat thresholdOutput = new Mat(); 
    int thresh = 150; 

    List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); 
    MatOfInt4 hierarchy = new MatOfInt4(); 

    Imgproc.threshold(source, thresholdOutput, thresh, 255, Imgproc.THRESH_BINARY); 
    //Imgproc.Canny(source, thresholdOutput, 50, 180); 
    Imgproc.findContours(source, contours, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); 
//  source = thresholdOutput; 
    RotatedRect minEllipse[] = new RotatedRect[contours.size()]; 

    for(int i=0; i<contours.size();i++){ 
     MatOfPoint2f temp=new MatOfPoint2f(contours.get(i).toArray()); 

     if(temp.size().height > minEllipseSize && temp.size().height < maxEllipseSize){ 
      double a = Imgproc.fitEllipse(temp).size.height; 
      double b = Imgproc.fitEllipse(temp).size.width; 
      if(Math.abs(a - b) < 10) 
       minEllipse[i] = Imgproc.fitEllipse(temp); 
     } 
    } 

    detectedObjects.clear(); 
    for(int i = 0; i< contours.size(); i++){ 
     Scalar color = new Scalar(180, 255, 180); 
     if(minEllipse[i] != null){ 
      detectedObjects.add(new DetectedObject(minEllipse[i].center)); 
      DetectedObject detectedObj = new DetectedObject(minEllipse[i].center); 
      Core.ellipse(source, minEllipse[i], color, 2, 8); 
     } 
    } 
} 
+0

Это на самом деле метод badvery для обнаружения эллипсов. Не удивительно, что это не будет работать в реальных изображениях. Попробуйте один из методов, о которых я упомянул, они будут работать намного лучше. Кроме того, удалите этот ответ и отредактируйте код в вопросе. – Miki

4

Реферирование к тексту:

Это превращается в HSV, как вы можете видеть красные области выглядят одинакового цвета как близлежащие деревья. Вот как я должен знать, что он красный, но я не могу.

Я хочу показать вам мой результат в основном то, что вы сделали (простые операции должны быть легко перенесены на андроид OpenCV):

// convert to HSV 
    cv::Mat hsv; 
    cv::cvtColor(input,hsv,CV_BGR2HSV); 

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

    // opencv = hue values are divided by 2 to fit 8 bit range 
    float red1 = 25/2.0f; 
    // red has one part at the beginning and one part at the end of the range (I assume 0° to 25° and 335° to 360°) 
    float red2 = (360-25)/2.0f; 

    // compute both thresholds 
    cv::Mat thres1 = channels[0] < red1; 
    cv::Mat thres2 = channels[0] > red2; 

    // choose some minimum saturation 
    cv::Mat saturationThres = channels[1] > 50; 

    // combine the results 
    cv::Mat redMask = (thres1 | thres2) & saturationThres; 

    // display result 
    cv::imshow("red", redMask); 

Это мои результаты:

enter image description here

enter image description here

Из вашего результата, пожалуйста, mi что findContours изменяет входное изображение, поэтому, возможно, вы извлекли эллипс, но больше не видите его в изображении, если вы сохранили изображение AFTER findContours.

+0

Я попробую, как вы, но преобразуйте его в Java. Но просто, чтобы сообщить вам, я пробовал некоторое время назад тот же метод в OpenCV и OpenCV для Android, и тот, который был для Android, дал мне намного худший результат. – skyhawk

+0

Каков диапазон значений HUE в android openCV? Это '0..180' или' 0..360'? – Micka

+0

Значения HUE идут от 0 до 179, другие идут до 255 – skyhawk

1

Вы пытались использовать opencv ORB? он работает очень хорошо. Я создал каскад хара для дорожного знака (круговое движение в моем случае) и использовал opencv ORB для сопоставления функций и устранения любых ложных срабатываний. Для распознавания образов использовался тензор Google и результаты были впечатляющими.