c# - OpenCV - 创建颜色 mask

标签 c# python c++ windows opencv

friend 们!有两个输入图像。一张背景图片,另一张蒙版图片。我需要拿到面具的彩色部分。

我需要得到的: background , mask , result image

但我得到了完全不同的东西:background , mask , result image

我的代码在 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");

第一个问题:如何才能达到图中所示的效果?

第二个问题:为什么不转换mask会报错:(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 背景下,您不会在此处的第二张图片上看到透明度):

White background

Transparent background

关于c# - OpenCV - 创建颜色 mask ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54940660/

相关文章:

c# - 使用 ffmpeg 转换图像序列

c# - 如何在 C# 中正确关闭 winforms 应用程序?

c# - XNA - 以正确的顺序绘制四边形(和基元)

python - Python 和 C 之间 ntohl 和 htonl 的不同行为

C++ : other one simple scope guard

c# - 使用反射从 PropertyType 获取字节数

python - 如何在不实例化的情况下进行赋值

python - 使用 excel 值在 python 中执行计算

c++ - 没有计数器的递归方法如何计数?

c++ - 让数组与 toupper 一起工作