2015-07-29 4 views
0

Предположим, у меня есть изображение. Я в основном хочу сделать границу по определенному цвету, который я хочу. Я знаю минимальные и максимальные скалярные значения hsv этого цвета. Но я не знаю, как двигаться дальше.Как я могу нарисовать границу по определенному цвету в opencv?

#include <iostream> 
#include "opencv2/highgui/highgui.hpp" 
#include "opencv2/imgproc/imgproc.hpp" 
#include<stdio.h> 
#include<opencv2/opencv.hpp> 
using namespace cv; 
using namespace std; 
int main(int argc, char** argv) 
{ 
    VideoCapture cap(0); 
    while(true) 
    { 
    Mat img; 
    cap.read(img); 
    Mat dst; 
    Mat imghsv; 
    cvtColor(img, imghsv, COLOR_BGR2HSV); 
    inRange(imghsv, 
      Scalar(0, 30, 0), 
      Scalar(20, 150, 255), 
      dst 
      ); 
    imshow("name",dst); 
    if (waitKey(30) == 27) //wait for 'esc' key press for 30ms 
     { 
      cout << "esc key is pressed by user" << endl; 
      break; 
     } 
    } 
} 

Функция попадани в диапазон работает хорошо, но я не могу провести границу через любой белый (я имею в виду в зависимости от того пиксель находится в указанном диапазоне)

+0

вы должны размещать больше информации: эталонное изображение, язык программирования, ваши HSV ограничивающей – Miki

+0

т.е. [mcve] (http://stackoverflow.com/help/mcve) – kkuilla

+0

Поскольку вы обновили свой вопрос с некоторыми код, я также обновил свой ответ с помощью некоторого кода! Проверьте это и посмотрите, соответствует ли он вашим потребностям. (В следующий раз, пожалуйста, сообщите людям, что вы обновили вопрос с комментариями к их ответам) – Miki

ответ

1

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

СЕГМЕНТ ЦВЕТ

Работа в HSV в целом является хорошей идеей для цветов сегмента. Когда у вас есть правильная нижняя и верхняя граница, вы можете легко сегментировать цвет. Простым подходом является использование inRange. Вы можете найти, как его использовать here например.

НАЙТИ ГРАНИЦЫ

После того как вы двоичная маска (полученную через сегментацию), вы можете найти ее границы с помощью findContours. Вы можете обратиться к this или this, чтобы узнать, как использовать findContours, чтобы обнаружить границу, и drawContours, чтобы нарисовать его.


UPDATE

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

#include<opencv2/opencv.hpp> 
#include <iostream> 

using namespace std; 
using namespace cv; 

int main(int argc, char** argv) 
{ 
    VideoCapture cap(0); 
    while (true) 
    { 
     Mat img; 
     cap.read(img); 
     Mat dst; 
     Mat imghsv; 
     cvtColor(img, imghsv, COLOR_BGR2HSV); 
     inRange(imghsv, Scalar(110, 100, 100), Scalar(130, 255, 255), dst); // Detect blue objects 


     // Remove some noise using morphological operators 
     Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(7,7)); 
     morphologyEx(dst, dst, MORPH_OPEN, kernel); 

     // Find contours 
     vector<vector<Point>> contours; 
     findContours(dst.clone(), contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); 

     // Draw all contours (green) 
     // This 
     drawContours(img, contours, -1, Scalar(0,255,0)); 

     // If you want to draw a contour for a particular one, say the biggest... 

     // Find the biggest object 
     if (!contours.empty()) 
     { 
      int idx_biggest = 0; 
      int val_biggest = contours[0].size(); 

      for (int i = 0; i < contours.size(); ++i) 
      { 
       if (val_biggest < contours[i].size()) 
       { 
        val_biggest = contours[i].size(); 
        idx_biggest = i; 
       } 
      } 

      // Draw a single contour (blue) 
      drawContours(img, contours, idx_biggest, Scalar(255,0,0)); 

      // You want also the rotated rectangle (blue) ? 

      RotatedRect r = minAreaRect(contours[idx_biggest]); 

      Point2f pts[4]; 
      r.points(pts); 
      for (int j = 0; j < 4; ++j) 
      { 
       line(img, pts[j], pts[(j + 1) % 4], Scalar(0, 0, 255), 2); 
      } 
     } 

     imshow("name", dst); 
     imshow("image", img); 

     if (waitKey(30) == 27) //wait for 'esc' key press for 30ms 
     { 
      cout << "esc key is pressed by user" << endl; 
      break; 
     } 
    } 
} 
0

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

на канале цветового тона (IMG):

cv::Mat mask = cv::Mat::zeros(img.size(),CV_8UC1); 

for(int i=0;i<img.rows;i++){ 
    for(int j=0;j<img.cols;i++){ 
     if(img.at<uchar>(i,j)==(uchar)specific_hue){ 
      mask.at<uchar>(i,j)=(uchar)255; 
     } 
    } 
} 

color_img.copyTo(masked_image, mask); 

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

cv::Mat mask = cv::Mat::zeros(img.size(),CV_8UC1); 
int threshold = 5; 

for(int i=0;i<img.rows;i++){ 
    for(int j=0;j<img.cols;i++){ 
     if((img.at<uchar>(i,j)>(uchar)(specific_hue - threshold)) && (img.at<uchar>(i,j)<(uchar)(specific_hue + threshold))){ 
      mask.at<uchar>(i,j)=(uchar)255; 
     } 
    } 
} 

color_img.copyTo(masked_image, mask); 
+0

вы знаете, что 'inRange' делает это точно? Кроме того, я не вижу в ответе части о рисовании границ. – Miki

+0

Нет, я не знал эту функцию, так как это было очень быстро. Спасибо за информацию. Для контура, с другой стороны, я обнаружил, что маска может быть хорошим началом, а затем применить то, что вы хотите для контура (который не был указан автором). Я думал, например, что-то вроде fitEllipse Но я согласен с тем, что в моем ответе не хватает этой информации. – AdMor

+1

Хотя ваша петля работает нормально в целом, для сегментации цветов HSV вы также должны добавить ограничение на значение S и V, обычно для того, чтобы иметь как> 100 (или вы сегментируете также очень темные, и черные цвета). Поэтому для вашего подхода к работе вы также должны включить это. Вы также повторяете два раза по строкам, второй цикл должен быть 'j Miki

Смежные вопросы