0

我用 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、... 不存在。

那是带有 alpha 的原始图像:image original

那是带有“提取的白色”的图像:图像原始

那是带有“提取的黑色”的图像: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;
}

提前感谢))

4

2 回答 2

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 >= 0max <= 255min < max

首先,您必须确保亮度在 min ... max 范围内,否则您的结果将超出范围 0 ... 255。您也可以在之后限制输出范围,但无论如何您必须范围检查。

然后从亮度中减去 min 。现在您有一个介于 0 和 (max - min) 之间的值。通过除以 (max - min),您会得到一个介于 0 和 1 之间的值。将结果乘以 255,您会得到所需范围 0 ... 255 内的值。

此外,您必须意识到您正在执行整数运算。因此,先乘以 255,然后再除。如果您从除法开始,您会得到 0 或 1 作为中间结果(因为整数运算不会产生小数,最终结果将是 0 或 255,并且所有灰色调都会丢失。

于 2014-12-13T13:34:01.487 回答
0

The effect you are seeing is called banding or posterisation. It is caused by making contrast stretches to data that is not sampled with sufficient bit-depth. As you only have 8-bit data, you only have 255 grey levels. If you stretch the 50 levels between 100-150 over a range of 255 levels, there will be gaps in your histogram around 5 levels wide. The solution is either to obtain 16-bit data, or make less drastic changes in the contrast.

Alternatively, if like me, you are a photographer, and more interested in the aesthetics of the image than its scientific accuracy, you can add a small amount of random noise to disguise and "smear over" the banding...

There is a nice description here.

I can also show you an example with ImageMagick, first we create two greyscale ramps (gradients), one 8-bit and one 16-bit, both ranging from brightness level 100 to 150 like this:

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

They look like this:

enter image description here enter image description here

If I now stretch them both to the full range of 0-255 you will immediately see the banding effect in the 8-bit version, and the smoothness of the 16-bit version - which, incidentally, is the reason for using RAW format (12-14 bit) on your camera rather than shooting 8-bit JPEGs:

convert gradient8.png  -auto-level out8.png
convert gradient16.png -auto-level out16.png

enter image description here enter image description here

I alluded to using noise to redue the visibility of the banding effect, and you can do that using a technique like this:

convert out8.png -attenuate 0.3 +noise gaussian  out.png

which gives you a less marked effect, somewhat similar to film grain:

enter image description here

I am not certain exactly what you are trying to do, but if you just want to spread the brightness levels from 127-255 over the full range of 0-255, you can do that simply at the command-line like this:

convert orig.png -level 50%,100% whites.png

enter image description here

Likewise, if you want the brightness levels from 0-17 spread over the range 0-255, you can do

convert orig.png -level 0,6.66667% blacks.png

enter image description here

于 2014-12-16T22:59:35.373 回答