Я пишу программу на C #, но надеюсь, что C ++ и C # в фоновом режиме точно так же.
Что я хочу — взять изображение в градациях серого и разделить цвета более 127 и до 17, чтобы разделить изображения. Если я просто получаю «белые» цвета и программно растягиваю их от диапазона (127-255) до (0-255), как
// pseudocode
int min = 127, max = 255;
for(int x; x< width; x++)
pixels[x] = pixels[x]/(max-min) * max;
Тогда здесь будет не ровный интервал. Я имею в виду, что 127 конвертируется в 0, а 128 конвертируется в 2 и цвета 1,3,5, … не существуют.
Это оригинальное изображение с альфа:оригинал изображения
Это изображение с «извлеченным белым»:оригинал изображения
Это изображение с «извлеченным черным»: snorgg.ru/patchwork/tst_black.png.
Я не совсем понимаю, как это можно реализовать, поэтому экзаменационный код понравится:
{
im.MagickImage image = new im.MagickImage("c:/55/11.png");
im.MagickImage imageWhite = ExtractWhite(image);
im.MagickImage imageBlack = ExtractBlack(image);
}
....
public static im.MagickImage ExtractWhite(im.MagickImage img){
im.MagickImage result = new im.MagickImage(img);
?????
?????
return result;
}
заранее благодарю))
Я думаю, что ваш расчет неверен. Вы путаете входной диапазон с выходным. Диапазон ввода от мин до максимума, а выход от 0 до 255. Это совпадение, что ваш максимальный вход равен вашему максимальному выходу (255).
Если вы хотите растянуть значение в диапазоне min ... max
(= диапазон ввода) до 0 ... 255
(= выходной диапазон), затем рассчитайте это
int brightness = pixel[x];
if (brightness <= min) {
pixel[x] = 0;
} else if (brightness >= max) {
pixel[x] = 255;
} else {
pixel[x] = 255 * (brightness - min) / (max - min);
}
куда min >= 0
а также max <= 255
а также min < max
,
Сначала вы должны убедиться, что яркость находится в диапазоне min … max, иначе ваш результат превысит диапазон 0 … 255. Вы также можете ограничить диапазон выходного сигнала впоследствии, но в любом случае вы должны сделать проверка дальности.
Затем вычтите мин из яркости. Теперь у вас есть значение от 0 до (max — min). Делив на (max — min), вы получите значение от 0 до 1. Умножьте результат на 255, и вы получите значение в желаемом диапазоне 0 … 255.
Также вы должны знать о том, что вы выполняете целочисленную арифметику. Поэтому сначала умножьте на 255, а затем разделите. Если вы начнете с деления, вы получите 0 или 1 в качестве промежуточного результата (поскольку целочисленная арифметика не дает десятичных дробей, а конечный результат будет 0 или 255, и все серые тона будут потеряны.
Эффект, который вы видите, называется banding
или же posterisation
, Это вызвано контрастным растяжением данных, которые не были выбраны с достаточной битовой глубиной. Поскольку у вас есть только 8-битные данные, у вас есть только 255 уровней серого. Если вы растянете 50 уровней между 100-150 в диапазоне 255 уровней, в вашей гистограмме будут пробелы около 5 уровней в ширину. Решение заключается либо в получении 16-битных данных, либо в менее контрастных изменениях.
В качестве альтернативы, если вы, как и я, являетесь фотографом и более заинтересованы в эстетике изображения, чем в его научной точности, вы можете добавить небольшое количество случайного шума, чтобы замаскировать и «размазать» полосу …
Есть хорошее описание Вот.
Я также могу показать вам пример с ImageMagick: сначала мы создадим два градаций серого (градиенты), один 8-битный и один 16-битный, оба в диапазоне от уровня яркости 100 до 150 следующим образом:
convert -depth 8 -size 100x500 gradient:"rgb(100,100,100)-rgb(150,150,150)" -rotate 90 gradient8.png
convert -depth 16 -size 100x500 gradient:"rgb(100,100,100)-rgb(150,150,150)" -rotate 90 gradient16.png
Они выглядят так:
Если я теперь растяну их до полного диапазона 0-255, вы сразу увидите эффект полосатости в 8-битной версии и плавность 16-битной версии — что, кстати, является причиной использования формата RAW ( 12-14 бит) на вашей камере вместо съемки 8-битных JPEG:
convert gradient8.png -auto-level out8.png
convert gradient16.png -auto-level out16.png
Я упоминал об использовании шума, чтобы уменьшить видимость эффекта полос, и вы можете сделать это, используя такую технику:
convert out8.png -attenuate 0.3 +noise gaussian out.png
что дает вам менее заметный эффект, чем-то похожий на зернистость пленки:
Я не уверен, что именно вы пытаетесь сделать, но если вы просто хотите распределить уровни яркости от 127 до 255 по всему диапазону от 0 до 255, вы можете сделать это просто в командной строке следующим образом:
convert orig.png -level 50%,100% whites.png
Аналогично, если вы хотите, чтобы уровни яркости от 0 до 17 распространялись в диапазоне 0-255, вы можете сделать
convert orig.png -level 0,6.66667% blacks.png