OpenCV RGB одноканальное регулирование цвета
Входное изображение - это полное изображение RGB, выходное изображение B - это то же изображение, но с "скорректированными" значениями R
Мне нужно изменить масштаб значения RGB между 128 и 255, чтобы меньшие значения, чем 128, масштабировались до верхнего значения.
RMAX = 127
img = cv2.imread(filename) # load img
blue, green, red = cv2.split(img) # get single color
red = red*RMAX/255+128 # scale the color as I need
но это продолжает получать неправильное значение:
если красное значение равно 255 = 255*127/255+128, то должно вывести 255, но вернуть 128
Почему это случилось?
РЕДАКТИРОВАТЬ:
Значения цвета не нужно пересчитывать каждый раз. Было бы лучше подготовить массив в начале с диапазоном значений, а затем заменить текущее значение значением из массива?
ValuesForRed = [0]*255
for i in range(0,255):
ValuesForRed[i]=i*127 / 255 + 128
как заменить значения в массиве сейчас проблема...
следует заменить соответствующее значение на соответствующий индекс
i.e. red[45]= 0
ValuesForRed[0] = 128
red[45]= 128
начал новый вопрос в Python OpenCV cv2.LUT(), как использовать
2 ответа
Это происходит потому, что красный unsigned char
, который является числом в диапазоне от 0 до 255. Тем не менее, вы ожидаете red
вести себя как целое число.
Итак, учитывая, что
red = 255
red = red*127/255 + 128
Когда программа умножит красный *127, результат будет переполнен, потому что его значение будет больше 255, и поэтому ответ будет 0
(потому что 255*127 по модулю 255 = 0). Отсюда вы получаете red = red*127/255 + 128 = (255*127 modulo 255) / 255 + 128 = 0 /255 + 128 = 128
Чтобы это исправить, вы можете разыграть red
плавать, когда вы делаете над ним арифметические операции, например:
red = (float)red * 127 / 255
Редактировать Как указал Уильям red
это cv::Mat
типа CV_8U
, Вы можете конвертировать изображение в CV_32F
введите для расчетов, а затем преобразовать его обратно. Например (это код C++):
Mat red_float;
red.convertTo(red_float,CV_32F);
red_float = red_float*RMAX/255+128;
red_float.convertTo(red,CV_8U);
Другой вопрос, который возникает у ОП: "Как лучше решить эту проблему?". Вот как я бы подошел к этому. Это код C++, но вы должны легко его перевести на Python. Этот подход быстрый и нет необходимости конвертировать матрицы в CV_32F
тип.
Разделить входное изображение на каналы
Mat input_image; //input image vector<Mat> split_image(3); split(input_image, split_image); Mat red = split_image[2];
получать
mask_red
такое, что местоположение вmask_red
устанавливается на 255, если соответствующее местоположение вred
составляет от 129 до 255 (включительно в пределах), в противном случае он равен 0. Это может быть достигнуто с помощьюinRange()
функция.Mat mask_red; inRange(red, Scalar(129), Scalar(255), mask_red);
Сейчас подать заявку
setTo()
функция кred
установить все маскированные пиксели на 255.red.setTo(Scalar(255), mask_red);
Объедините каналы, чтобы сформировать окончательное изображение.
Mat output_image; // output image merge(split_image, output_image);