【发布时间】:2022-01-10 09:12:16
【问题描述】:
【问题讨论】:
【问题讨论】:
使用此功能可以保存带有 alpha 通道的 PNG 图像。到 这样做,创建 8 位(或 16 位)4 通道图像 BGRA,其中 阿尔法通道最后。完全透明的像素应该有 alpha 设置为 0,完全不透明的像素应将 alpha 设置为 255/65535(请参阅 下面的代码示例)。
透明图像带有一个额外的通道,我们称之为 alpha 通道,在 opencv 中用BGRA 表示。您需要做的就是创建一个格式为BGRA 的蒙版图像。然后检测图像中的所有黑色像素,并为这些黑色像素分配蒙版图像的 alpha 通道为 0。
注意: 使用 opencv imshow 或其他您将无法看到透明图像,因为 opencv 无法显示 alpha 通道。所以你需要用imwrite写成png格式。
注意:使任何像素透明意味着将其 Alpha 通道分配为 0。
这是我的意思的输出:
由于我不熟悉 python,所以我用 C++ 编写了这些步骤。很抱歉。
#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
int main()
{
cv::Mat img = cv::imread("/ur/input/img.png",cv::IMREAD_COLOR);
cv::Mat mask = cv::Mat::zeros(cv::Size(img.cols,img.rows),CV_8UC4);
cv::namedWindow("Input",0);
cv::namedWindow("Output",0);
for(int i=0; i<mask.cols; i++)
{
for(int j=0; j<mask.rows; j++)
{
if(img.at<cv::Vec3b>(cv::Point(i,j))[0] == 0 &&
img.at<cv::Vec3b>(cv::Point(i,j))[1] == 0 &&
img.at<cv::Vec3b>(cv::Point(i,j))[2] == 0)
{
mask.at<cv::Vec4b>(cv::Point(i,j))[0] = img.at<cv::Vec3b>(cv::Point(i,j))[0];
mask.at<cv::Vec4b>(cv::Point(i,j))[1] = img.at<cv::Vec3b>(cv::Point(i,j))[1];
mask.at<cv::Vec4b>(cv::Point(i,j))[2] = img.at<cv::Vec3b>(cv::Point(i,j))[2];
mask.at<cv::Vec4b>(cv::Point(i,j))[3] = 0;
}
else {
mask.at<cv::Vec4b>(cv::Point(i,j))[0] = img.at<cv::Vec3b>(cv::Point(i,j))[0];
mask.at<cv::Vec4b>(cv::Point(i,j))[1] = img.at<cv::Vec3b>(cv::Point(i,j))[1];
mask.at<cv::Vec4b>(cv::Point(i,j))[2] = img.at<cv::Vec3b>(cv::Point(i,j))[2];
mask.at<cv::Vec4b>(cv::Point(i,j))[3] = 255;
}
}
}
cv::imshow("Input",img);
cv::imshow("Output",mask);
cv::imwrite("/ur/writing/dir/transparent.png",mask);
cv::waitKey(0);
return 0;
}
【讨论】:
您可以像这样快速并矢量化:
import cv2
import numpy as np
# Load image as Numpy array in BGR order
na = cv2.imread('I5jKW.png')
# Make a True/False mask of pixels whose BGR values sum to more than zero
alpha = np.sum(na, axis=-1) > 0
# Convert True/False to 0/255 and change type to "uint8" to match "na"
alpha = np.uint8(alpha * 255)
# Stack new alpha layer with existing image to go from BGR to BGRA, i.e. 3 channels to 4 channels
res = np.dstack((na, alpha))
# Save result
cv2.imwrite('result.png', res)
注意事项:
1 您同样可以使用cv2.merge() 代替np.dstack(),它可能更快。
2 您同样可以使用 PIL/Pillow 代替 OpenCV 函数来读取/保存图像。
【讨论】:
这是在 Python/OpenCV/Numpy 中执行此操作的另一种方法。
import cv2
import numpy as np
# load image
img = cv2.imread('girl_on_black.png')
# threshold on black to make a mask
color = (0,0,0)
mask = np.where((img==color).all(axis=2), 0, 255).astype(np.uint8)
# put mask into alpha channel
result = img.copy()
result = cv2.cvtColor(result, cv2.COLOR_BGR2BGRA)
result[:, :, 3] = mask
# save resulting masked image
cv2.imwrite('girl_on_black_transparent.png', result)
# display result, though it won't show transparency
cv2.imshow("MASK", mask)
cv2.imshow("RESULT", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
【讨论】: