c # — ImageMagick — Установить уровни изображения в градациях серого

Я пишу программу на 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

Решение

Я думаю, что ваш расчет неверен. Вы путаете входной диапазон с выходным. Диапазон ввода от мин до максимума, а выход от 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, и все серые тона будут потеряны.

0

Другие решения

Эффект, который вы видите, называется 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

введите описание изображения здесь

0

По вопросам рекламы [email protected]