gpt4 book ai didi

python - 为具有透明度的 PNG 设置背景颜色

转载 作者:太空宇宙 更新时间:2023-11-03 20:54:34 28 4
gpt4 key购买 nike

我正在加载具有透明平面的 PNG 图像。当转换为灰度时,图像中的透明区域显示为黑色,这似乎是默认背景。我需要它们是白色的。我能做什么?

[这不是关于如何保持透明度的常见问题。]

最佳答案

最有效的方法(内存和 CPU)是让 libPNG这样做,使用 png_set_background:

If you don't need, or can't handle, the alpha channel you can call png_set_background() to remove it by compositing against a fixed color. Don't call png_set_strip_alpha() to do this - it will leave spurious pixel values in transparent parts of this image.

png_set_background(png_ptr, &background_color,
PNG_BACKGROUND_GAMMA_SCREEN, 0, 1);

The background_color is an RGB or grayscale value according to the data format libpng will produce for you.

不幸的是,libPNG 周围的 OpenCV 包装器没有使用它,因此您必须自己修补一些基本支持(由于将附加选项传递给 imread 的能力有限而受到阻碍)。

其他可能的方法是为此特定目的使用 libPNG 编写您自己的简单图像加载器。

如果你能承受一些浪费,将其加载为 BGRA,并进行一些后期处理。但是,我会比 Gabriel 引用的代码更进一步。并将颜色转换纳入其中。

void remove_transparency(cv::Mat const& source
, cv::Mat& destination
, uint8_t background_color)
{
CV_Assert(source.type() == CV_8UC4);

destination.create(source.rows, source.cols, CV_8UC1);

auto it_src(source.begin<cv::Vec4b>()), it_src_end(source.end<cv::Vec4b>());
auto it_dest(destination.begin<uint8_t>());

std::transform(it_src, it_src_end, it_dest
, [background_color](cv::Vec4b const& v) -> uchar
{
// Conversion constants taken from cvtColor docs...
float gray(v[0] * 0.114f + v[1] * 0.587f + v[2] * 0.299f);
float alpha(v[3] / 255.0f);
return cv::saturate_cast<uchar>(gray * alpha + background_color * (1 - alpha));
}
);
}

当然,这仍然是单线程的,所以让我们利用 cv::parallel_for_ 进一步改进它。

class ParallelRemoveTransparency
: public cv::ParallelLoopBody
{
public:
ParallelRemoveTransparency(cv::Mat const& source
, cv::Mat& destination
, uint8_t background_color)
: source_(source)
, destination_(destination)
, background_color_(background_color)
{
CV_Assert(source.size == destination.size);
}

virtual void operator()(const cv::Range& range) const
{
cv::Mat4b roi_src(source_.rowRange(range));
cv::Mat1b roi_dest(destination_.rowRange(range));

std::transform(roi_src.begin(), roi_src.end(), roi_dest.begin()
, [this](cv::Vec4b const& v) -> uint8_t {
float gray(v[0] * 0.114f + v[1] * 0.587f + v[2] * 0.299f);
float alpha(v[3] / 255.0f);
return cv::saturate_cast<uint8_t>(gray * alpha + background_color_ * (1 - alpha));
}
);
}

private:
cv::Mat const& source_;
cv::Mat& destination_;
uint8_t background_color_;
};

void remove_transparency(cv::Mat const& source
, cv::Mat& destination
, uint8_t background_color)
{
CV_Assert(source.type() == CV_8UC4);

destination.create(source.rows, source.cols, CV_8UC1);

ParallelRemoveTransparency parallel_impl(source, destination, background_color);
cv::parallel_for_(cv::Range(0, source.rows), parallel_impl);
}

原来你在 Python 中需要这个。这是替代方案的快速小草稿:

import numpy as np
import cv2

def remove_transparency(source, background_color):
source_img = cv2.cvtColor(source[:,:,:3], cv2.COLOR_BGR2GRAY)
source_mask = source[:,:,3] * (1 / 255.0)

background_mask = 1.0 - source_mask

bg_part = (background_color * (1 / 255.0)) * (background_mask)
source_part = (source_img * (1 / 255.0)) * (source_mask)

return np.uint8(cv2.addWeighted(bg_part, 255.0, source_part, 255.0, 0.0))


img = cv2.imread('smile.png', -1)
result = remove_transparency(img, 255)

cv2.imshow('', result)
cv2.waitKey()

关于python - 为具有透明度的 PNG 设置背景颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45611685/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com