Python:如何在RGB图像上实现二值滤波?(算法)

2024-06-26 14:46:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试使用python&PyQT5实现二值图像过滤器(以获得单色二进制图像),并且,为了检索新的像素颜色,我使用以下方法:

def _new_pixel_colors(self, x, y):
    color = QColor(self.pixmap.pixel(x, y))

    result = qRgb(0, 0, 0) if all(c < 127 for c in color.getRgb()[:3]) else qRgb(255, 255, 255)

    return result

这是不是一个正确的RGB图像二值滤波器样本?我的意思是,这是一个充分的条件来检查像素是亮还是暗,然后是(127,127,127)灰色? 并且请不要使用opencv、枕头等提供任何解决方案。我只是问算法本身。在


Tags: 方法图像self过滤器颜色def二进制像素
2条回答

我至少要和强度比较一下i=R+G+B。。。在

对于ROI类掩码,您可以使用任何阈值技术(自适应阈值化是最好的),但是如果您得到的图像不是ROI掩码,并且应该与原始图像的视觉特征相似,则我所知的最佳转换是使用Dithering。在

BW抖动背后的想法是将灰度转换成BW模式,以预先显示阴影。结果通常是嘈杂的,但保留了更多的视觉细节。这里简单的天真<强> C++ >强>抖动(对不起不是Python编码器):

picture pic0,pic1;
    // pic0 - source img
    // pic1 - output img
int x,y,i;
color c;
// resize output to source image size clear with black
pic1=pic0; pic1.clear(0);
// dithering
i=0;
for (y=0;y<pic0.ys;y++)
 for (x=0;x<pic0.xs;x++)
    {
    // get source pixel color (AARRGGBB)
    c=pic0.p[y][x];
    // add to leftovers
    i+=WORD(c.db[picture::_r]); // _r,_g,_b are just constants 0,1,2
    i+=WORD(c.db[picture::_g]);
    i+=WORD(c.db[picture::_b]);
    // threshold white intensity is 255+255+255=765
    if (i>=384){ i-=765; c.dd=0x00FFFFFF; } else c.dd=0;
    // copy to destination image
    pic1.p[y][x]=c;
    }

所以它和上面的链接是一样的,但是只使用黑白两种颜色。i是要放在图像上的累积强度。xs,ys是分辨率,c.db[]是颜色通道访问。在

如果我像这样在彩色图像上应用这个:

input

结果如下:

output

正如你所看到的所有细节都保留了下来,但是一个嘈杂的图案出现了。。。出于打印目的,有时会将图像的分辨率放大以提高质量。如果你用一个更好的模式(比如16x16平方等等)改变naive2nestedforloops,那么噪声将在其源限制伪影附近得到保存。还有一些方法使用伪随机模式(将剩余的i放在其源像素附近的随机位置),这是更好的。。。在

但是对于BW抖动,即使是幼稚的方法也足够了,因为伪影只有一个像素大小。对于彩色抖动,伪影可能会产生几个像素大小的不需要的水平线图案(取决于使用的调色板不匹配越差的调色板越大的伪影…)

PS只是为了与其他应答阈值输出进行比较,这是同一张抖动图像:

inputoutput

Image thresholding是您要查找的算法类-二进制阈值将像素设置为0或1,是的。在

根据所需的输出,考虑先使用亮度通道将图像转换为其他颜色空间,尤其是HSL。使用(127, 127, 127)作为阈值并没有统一考虑亮度,因为RGB的每个通道都是R、G或B的饱和;请考虑以下图像:

Original Image

127, 127, 127 RGB Threshold

50% Luminance HSL Threshold

from PIL import Image
import colorsys


def threshold_pixel(r, g, b):
    h, l, s = colorsys.rgb_to_hls(r / 255., g / 255., b / 255.)
    return 1 if l > .36 else 0
    # return 1 if r > 127 and g > 127 and b > 127 else 0


def hlsify(img):
    pixels = img.load()
    width, height = img.size

    # Create a new blank monochrome image.
    output_img = Image.new('1', (width, height), 0)
    output_pixels = output_img.load()

    for i in range(width):
        for j in range(height):
            output_pixels[i, j] = threshold_pixel(*pixels[i, j])

    return output_img


binarified_img = hlsify(Image.open('./sample_img.jpg'))
binarified_img.show()
binarified_img.save('./out.jpg')

在其他StackExchange网站上有很多关于这个话题的讨论,例如

Binarize image data

How do you binarize a colored image?

how can I get good binary image using Otsu method for this image?

相关问题 更多 >