最有效的方法(内存和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<:vec4b>()), it_src_end(source.end<:vec4b>());
auto it_dest(destination.begin());
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(gray * alpha + background_color * (1 - alpha));
}
);
}
{cd3>这当然是一点改进。在
^{pr2}$
结果你在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()