c# - OpenCV - 创建颜色蒙版
问题描述
朋友们!有两个输入图像。一个背景图像,另一个蒙版图像。我需要得到面具的彩色部分。
我的代码在 C# 中:
//Read files
Mat img1 = CvInvoke.Imread(Environment.CurrentDirectory + "\\Test\\All1.jpg");
Mat img = CvInvoke.Imread(Environment.CurrentDirectory + "\\Test\\OriginalMask.jpg");
// Threshold and MedianBlur mask
CvInvoke.Threshold(img, img, 0, 255, Emgu.CV.CvEnum.ThresholdType.BinaryInv);
CvInvoke.MedianBlur(img, img, 13);
// without this conversion, an error appears: (mtype == CV_8U || mtype == CV_8S) && _mask.sameSize(*psrc1)
CvInvoke.CvtColor(img, img, Emgu.CV.CvEnum.ColorConversion.Rgb2Gray);
CvInvoke.BitwiseNot(img1, img1, img);
//Save file
img1.Save(Environment.CurrentDirectory + "\\Test\\Result.jpg");
第一个问题:如何才能达到图片所示的效果?
第二个问题:不转换掩码为什么会报错: (mtype == CV_8U || mtype == CV_8S) && _mask.sameSize(*psrc1)
第三个问题:如何在最终图像中制作透明背景而不是白色背景?
解决方案不必在 C# 中。该解决方案适用于任何编程语言,因为语法 OpenCV 大致相同。先感谢您。
解决方案
我将在我的回答中使用 C++,因为我最熟悉它。
这是我的建议:
// Load background as color image.
cv::Mat background = cv::imread("background.jpg", cv::IMREAD_COLOR);
// Load mask image as grayscale image.
cv::Mat mask = cv::imread("mask.jpg", cv::IMREAD_GRAYSCALE);
// Start time measurement.
auto start = std::chrono::system_clock::now();
// There are some artifacts in the JPG...
cv::threshold(mask, mask, 128, 255, cv::THRESH_BINARY);
// Initialize result image.
cv::Mat result = background.clone().setTo(cv::Scalar(255, 255, 255));
// Copy pixels from background to result image, where pixel in mask is 0.
for (int x = 0; x < background.size().width; x++)
for (int y = 0; y < background.size().height; y++)
if (mask.at<uint8_t>(y, x) == 0)
result.at<cv::Vec3b>(y, x) = background.at<cv::Vec3b>(y, x);
// End time measurement.
auto end = std::chrono::system_clock::now();
// Output duration duration.
std::chrono::duration<double> elapsed_seconds = end - start;
std::cout << elapsed_seconds.count() << "\n";
// Write result.
cv::imwrite("result.png", result);
// Start time measurement.
start = std::chrono::system_clock::now();
// Generate new image with alpha channel.
cv::Mat resultTransparent = cv::Mat(result.size(), CV_8UC4);
// Copy pixels in BGR channels from result to transparent result image.
// Where pixel in mask is not 0, set alpha to 0.
for (int x = 0; x < background.size().width; x++)
{
for (int y = 0; y < background.size().height; y++)
{
resultTransparent.at<cv::Vec4b>(y, x)[0] = result.at<cv::Vec3b>(y, x)[0];
resultTransparent.at<cv::Vec4b>(y, x)[1] = result.at<cv::Vec3b>(y, x)[1];
resultTransparent.at<cv::Vec4b>(y, x)[2] = result.at<cv::Vec3b>(y, x)[2];
if (mask.at<uint8_t>(y, x) != 0)
resultTransparent.at<cv::Vec4b>(y, x)[3] = 0;
else
resultTransparent.at<cv::Vec4b>(y, x)[3] = 255;
}
}
// End time measurement.
end = std::chrono::system_clock::now();
// Output duration duration.
elapsed_seconds = end - start;
std::cout << elapsed_seconds.count() << "\n";
// Write transparent result.
cv::imwrite("resultTransparent.png", resultTransparent);
结果在这两个输出中(您不会在白色 StackOverflow 背景上看到第二张图像的透明度):
推荐阅读
- reactjs - 如何在 React 中重定向而不重置 Redux Store?
- api - API(公共)获取最新稳定的 VSCode 版本,可从 update.code.visualstudio.com/api 下载
- c# - .NET Web API 无法公开/运行
- javascript - 如何在两个刻度之间更改条形颜色 - Plotly.js
- java - 通过 s3 触发时如何验证 lambda 是否已完成执行?
- android - 从 Android 和 iOS 应用程序中删除对 Gen#1 ChromeCast 设备的支持
- java - 如何使用 Java API 从 Dialogflow CX 检测意图并将代理响应作为音频和文本获取?
- office365 - 身份验证失败,因为远程方已关闭传输流 - 发送 smtp 错误
- maven - 从 Maven 依赖项中排除 .properties 文件
- python - 为什么枕头和 numpy 有时(但不是所有时间)会错误地转换我的图像?