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);
    
Другие вопросы по тегам