OpenCV cvtColor също променя оригиналното изображение

Имам функция, която взема изображение, преобразува го в HSV и задава V на 100. Изглежда обаче, че променя и оригиналното изображение.

Mat hsvfilter(const Mat& img) {
  Mat result;
  cvtColor(img, result, CV_BGR2HSV);
  for (int j = 0; j < img.rows; j++)
    for (int i = 0; i < img.cols; i++)
      result.at<Vec3d>(i, j)[2] = 100;
  return result;
}

Ето как го наричам:

Mat original = imread( "pic.png" );
Mat converted = hsvfilter(original);

namedWindow( "original", CV_WINDOW_AUTOSIZE );
imshow( "original", original );

namedWindow( "converted", CV_WINDOW_AUTOSIZE );
imshow( "converted", converted );

waitKey(0);

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

РЕДАКТИРАНЕ: ЕТО ФИКСИРАНИЯ КОД

Mat hsvfilter(const Mat& img) {
  Mat result;
  cvtColor(img, result, CV_BGR2HSV);
  for (int j = 0; j < result.rows; j++) {
    for (int i = 0; i < result.cols; i++) {
      result.at<cv::Vec3b>(j, i)[2] = 100;
    }
  }
  return result;
}

person BinRoot    schedule 15.03.2015    source източник
comment
За проверка на здравината опитайте да проверите дали проблемът продължава, ако направите Mat converted = hsvfilter(original.clone());. Чрез клониране няма начин функцията да има достъп до паметта на original.   -  person ChronoTrigger    schedule 16.03.2015


Отговори (1)


  1. Вашата функция hsvFilter трябва да изглежда така:

    Mat hsvfilter(const Mat& img) {
    Mat result;
    cvtColor(img, result, CV_BGR2HSV);
    for (int j = 0; j < result.rows; j++) //you are modyfying "result" object, not img
       for (int i = 0; i < result.cols; i++) //same as above
          result.at<Vec3d>(j, i)[2] = 100; //OpenCV uses (y,x) indexing
    return result;
    }
    

    В тази ситуация няма разлика в използването на img.cols, img.rows / result.cols, result.rows, защото размерът на двата масива (изображения) е еднакъв, но като цяло не забравяйте за това :) Вторият коментар не се нуждае от повече обяснения.

  2. Като цяло вашият код изглежда добре, според мен трябва да работи. Опитахте ли да го тествате, без да извиквате функцията hsvFilter (просто покажете оригиналното изображение)?

  3. Ако искате да запазите създадените прозорци за известно време, използвайте този код вместо waitKey(0);:

    while(waitKey(100) != 'q')
    {
        //all imshow calls
    }
    

Сега, когато искате да излезете, просто натиснете 'q' (трябва да имате активен един от прозорците на вашето приложение).

person cyriel    schedule 16.03.2015
comment
Проблемът беше, че OpenCV използва (y,x) индексиране. Вероятно имах достъп до матрицата извън границите и вместо C++ да изведе грешка, той просто модифицира паметта на оригиналната матрица. - person BinRoot; 16.03.2015