2015-08-04 3 views
0

Итак, я пытаюсь добавить скалярное значение ко всем элементам объекта Mat в openCV, однако для типов raw_t_ubit8 и raw_t_ubit16 я получаю неправильные результаты. Вот код.Добавление скаляра в объект Mat

Mat A; 
//Initialize Mat A; 
A = A + 0.1; 

Матрица изначально enter image description here

В результате сложения точно та же матрица. Эта проблема не возникает, когда я пытаюсь добавить скаляры к типам матриц raw_t_real. По raw_t_ubit8 я имею в виду, что глубина равна CV_8UC1

+0

Я не знаю, какой тип raw_t_real (google не говорит мне) ... Вы пробовали: http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#add? Возможно, перегруженный оператор «+» не определен для всех типов. –

+0

от raw_t_ubit8 Я имею в виду, что Mat A создается A.create (sizes_height, sizes_width, CV_8UC1), и да, я тоже пробовал добавить, дает тот же результат. –

+1

Если вы создали его с помощью CV_8UC1, он не может содержать значения, которые вы упомянули. – Antonio

ответ

2

Как указано в комментариях и в ответе @ Антонио, вы не можете добавить 0,1 к целому числу.

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

Mat1b A; // <-- type CV_8UC1 
... 
A += 0.1 * 255; 

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

Это эквивалентно ответу Антонио, но в результате получается более чистый код (по крайней мере, для меня). Тот же код будет использоваться, если вы суммируете double или Scalar. Scalar объект будет создан в обоих направлениях с помощью:

template<typename _Tp> inline 
Scalar_<_Tp>::Scalar_(_Tp v0) 
{ 
    this->val[0] = v0; 
    this->val[1] = this->val[2] = this->val[3] = 0; 
} 

Однако, если вам нужно суммировать точно 0,1 до вашей матрицы (и не растягивать его на 255), необходимо преобразовать матрицу CV_32FC1:

#include <opencv2/opencv.hpp> 
using namespace cv; 

int main(int, char** argv) 
{ 
    Mat1b A = (Mat1b(3,3) << 1,2,3,4,5,6,7,8,9); 

    Mat1f F; 
    A.convertTo(F, CV_32FC1); 
    F += 0.1; 

    return 0; 
} 
+0

Вы также знаете, как обрабатывается насыщенность? Я думаю, что это может быть полезной информацией для добавления. Кстати, я не думаю, что неявное кастинг ('double' ->' cv :: Scalar') обязательно является чистым кодом :) – Antonio

+0

Если результат операции нужно выполнить, как в этом случае, то в конечном счете 'saturated_cast' называется. – Miki

+1

@ Антонио Я согласен, добавил «(по крайней мере, для меня)», поскольку это, очевидно, основано на мнениях. Добавлена ​​также вещь «saturated_cast». – Miki

2

Если, как вы упомянули в комментариях, содержащиеся значения масштабируются в матрице, чтобы соответствовать целочисленному домену 0..255, тогда вы также должны масштабировать скалярное значение, которое вы суммируете. А именно:

A = A + cv::Scalar(round(0.1 * 255)); 

Или еще лучше:

A += cv::Scalar(round(0.1 * 255)); 

Обратите внимание, что резюме :: Скалярное, как указано в комментариях по Miki, в любом случае, сделанной из двойной (это cv::Scalar_<double>). Округление может быть опущено, но тогда вы оставляете выбор о том, как преобразовать двойной объект в целое число в реализацию функции. Вы также должны проверить, что происходит, когда значения насыщаются.

Documentation for Opencv matrix expressions.

+0

Я думаю, что вы можете избежать 'cv :: Scalar (int (round (...) ...))'. Умножение выполняется внутри по удвоению, тогда результат «насыщенный_программирован» на тип A. Так что просто 'A + = (0.1 * 255);' должен работать. Вы можете проверить? – Miki

+0

@Miki Если я не ошибаюсь, 'operator +' для 'cv :: Mat' не выполняет умножение. Хотя я думаю, что это делает для 'cv :: Rect' (суммирование cv :: Size - это операция масштабирования). – Antonio

+0

_addition_, извините. 'A + = 0.1 * 255;' works .. – Miki

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