Как правильно (лучший) способ установить значение cv :: Scalar для пикселя в cv :: Mat в opencv?

0

У меня есть объект cv::Mat,

cv::Mat _a ...

... и cv::Scalar object,

cv::Scalar _b ...

Каков правильный (лучший) способ установить значение _b на пиксель (в позиции (x, y)) в _a?

Обратите внимание, что объект _a может иметь 1, 2, 3, 4 канала, но код должен работать во всех случаях, то есть:

  • когда _a имеет 1 канал, первый элемент _b должен быть назначен в соответствующем положении
  • когда _a имеет 2 канала, первый элемент _b должен быть назначен первому каналу, а второй элемент _b должен быть назначен второму каналу, как в соответствующем положении
  • (....)
  • 2
    Вы можете использовать функцию Mat::at<Vec4> и затем перебирать от 0 до Mat::channels-1 Mat::at<Vec4> Mat::channels-1 по результату, создавая / присваивая Scalar
  • 0
    @Simson, но вы должны заметить, что Vec4 не является типом из opencv, в этом случае доступны следующие типы: Vec4b, Vec4d, Vec4f, Vec4i, Vec4s и Vec4w. Если правильный тип не известен заранее (как в этом случае), мы можем получить ошибку.
Показать ещё 1 комментарий
Теги:
opencv

3 ответа

1
Лучший ответ

cv::Mat имеет перегруженный operator= который принимает cv::Scalar. Это точный характер поведения, который вы желаете. К сожалению, нет прямого способа присвоить значения Scalar пикселям. Тем не менее, вы можете создать интересующую область, содержащую один пиксель, в координатах (x, y) и присваивать Scalar этому:

cv::Mat a; // contains data
cv::Scalar b(1,2,3,4);

cv::Range xr(x, x + 1);
cv::Range yr(y, y + 1);
a(xr, yr) = b;
  • 0
    Нет, извините, я хочу установить значение только для одного пикселя, то есть значение изображения в позиции (x, y).
  • 0
    О, спасибо большое !! Я уже много пробовал, но не могу получить чистое решение ... Вот почему я спрашиваю, как лучше это сделать.
Показать ещё 2 комментария
0

Я бы не использовал функцию.at из opencv. Его медленно, когда вы повторяете большую картину. Получите некоторые структуры, готовые, например, для изображений RGB:

 #pragma pack(push, 2)
  struct RGB {        //members are in "bgr" order!
     uchar blue;
     uchar green;
     uchar red;  };

Затем создайте указатель на строку сканирования изображения следующим образом:

RGB& rgb = image.ptr<RGB>(y)[x]; //y = row, x = col

Затем вы можете присвоить значения следующим образом:

cv::Scalar(image.ptr<RGB>(y)[x].value[0], image.ptr<RGB>(y)[x].value[1], image.ptr<RGB>(y)[x].value[2]);
0

Это не очень приятно или лаконично, но вы можете переключать возможные типы Mat и перебирать каналы Mat для создания/назначения Scalar. Что-то вроде этого:

void getPixel(Mat m, int x, int y, Scalar &pixel) {
    switch (m.depth()) {
    case 0:
        for (size_t i =  0; i < m.channels(); ++i) pixel[i] = m.at<uchar>(x, y);
        break;
    case 1:
        for (size_t i =  0; i < m.channels(); ++i) pixel[i] = m.at<char>(x, y);
        break;
    case 2:
        for (size_t i =  0; i < m.channels(); ++i) pixel[i] = m.at<ushort>(x, y);
        break;
    case 3:
        for (size_t i =  0; i < m.channels(); ++i) pixel[i] = m.at<short>(x, y);
        break;
    case 4:
        for (size_t i =  0; i < m.channels(); ++i) pixel[i] = m.at<long>(x, y);
        break;
    case 5:
        for (size_t i =  0; i < m.channels(); ++i) pixel[i] = m.at<float>(x, y);
        break;
    case 6:
        for (size_t i =  0; i < m.channels(); ++i) pixel[i] = m.at<double>(x, y);
        break;
    }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню