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). Я, вероятно, обращался к матрице за пределами границ, и вместо того, чтобы С++ выдавал ошибку, он просто модифицировал память исходной матрицы. - person BinRoot; 16.03.2015