Swift代码中的抗锯齿像素被转换为OpenCV中不需要的黑色像素。

3
我正在尝试使用Swift代码使一些像素变透明,方法是将抗锯齿设置为true并将路径像素删除而变成透明。 为了进一步处理,我使用C ++将UIimage发送到opencv,它可以将路径边缘转换为黑色像素。 我想删除由opencv生成的不需要的黑色像素。 如何删除这些黑色像素?
在opencv中,只需将图像转换为mat,然后从mat转换为UIImage,就会出现相同的问题。
Swift代码:
guard let imageSize=image.size else{
            return
        }
        UIGraphicsBeginImageContextWithOptions(imageSize,false,1.0)
        guard let context = UIGraphicsGetCurrentContext() else{
            return
        }
        context.setShouldAntialias(true)
        context.setAllowsAntialiasing(true)
        context.setShouldSubpixelQuantizeFonts(true)
        context.interpolationQuality = .high
        imgCanvas.image?.draw(in: CGRect(x: 0, y:0, width: (imgCanvas.image?.size.width)!, height: (imgCanvas.image?.size.height)!))
        bezeirPath = UIBezierPath()
        bezeirPath.move(to: fromPoint)
        bezeirPath.addLine(to: toPoint)
        bezeirPath.lineWidth=(CGFloat(widthOfLine) * scaleX )/scrollView.zoomScale
        bezeirPath.lineCapStyle = CGLineCap.round
        bezeirPath.lineJoinStyle=CGLineJoin.round
        bezeirPath.flatness=0.0
        bezeirPath.miterLimit=0.0
        bezeirPath.usesEvenOddFillRule=true
        UIColor.white.setStroke()
        bezeirPath.stroke(with: .clear, alpha:0)
        bezeirPath.close()
        bezeirPath.fill()
        UIColor.clear.set()
        context.addPath(bezeirPath.cgPath)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

OpenCV 代码:

Mat source;
    UIImageToMat(originalImage,source,true);

    return MatToUIImage(source);

我尝试了各种方法来解决这个问题,查看了不同的资料,但都没有解决。我已经试图解决这个问题三天了。所以如果有人有任何与此问题相关的线索,那将会很有帮助! [图片显示在透明边缘附近有黑色像素,这些是不需要的像素,这些黑色像素是由OpenCV产生的[1]


请问您能展示一下它在做什么,以及您希望它的样式如何吗? - Jeshua Lacock
透明像素的边缘有黑色像素需要变成透明。 - Pratap
你在OpenCV中处理图片做了什么?你能展示一下你尝试创建的最终图片的例子吗? - Jeshua Lacock
这个图像必须有 alpha 通道(例如透明度)吗?它将在 OpenCV 中与另一个图像合成吗? - Jeshua Lacock
图片需要具有透明度,不要与其他图像混合。 - Pratap
显示剩余3条评论
2个回答

0

我会将RGB图像和A掩码作为单独的图像提供给OpenCV。将您的掩码绘制到单通道图像中:

guard let imageSize=image.size else{
        return
    }
    UIGraphicsBeginImageContextWithOptions(imageSize,false,1.0)
    guard let context = UIGraphicsGetCurrentContext() else{
        return
    }
    context.setShouldAntialias(true)
    context.setAllowsAntialiasing(true)
    context.setShouldSubpixelQuantizeFonts(true)
    context.interpolationQuality = .high
    context.setFillColor(UIColor.black.cgColor)
    context.addRect(CGRect(x: 0, y: 0, width: imageSize.width, height: imageSize.height))
    context.drawPath(using: .fill)
    bezeirPath = UIBezierPath()
    bezeirPath.move(to: fromPoint)
    bezeirPath.addLine(to: toPoint)
    bezeirPath.lineWidth=(CGFloat(widthOfLine) * scaleX )/scrollView.zoomScale
    bezeirPath.lineCapStyle = CGLineCap.round
    bezeirPath.lineJoinStyle=CGLineJoin.round
    bezeirPath.flatness=0.0
    bezeirPath.miterLimit=0.0
    bezeirPath.usesEvenOddFillRule=true
    UIColor.white.setStroke()
    bezeirPath.stroke()
    bezeirPath.close()
    bezeirPath.fill()
    let maskImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

然后在OpenCV中,您可以将A图像应用于RGB图像。

Mat source, sourceMask
UIImageToMat(image, source, true)
UIImageToMat(maskImage, sourceMask, true)

如果您的图像不是RGB格式,您可以进行转换:
cvtColor(source, source, CV_RGBA2RGB)

如果您的掩码不是单通道的,您可以进行转换:
cvtColor(sourceMask, sourceMask, CV_RGBA2GRAY)

然后将RGB图像分成通道:

Mat rgb[3];
split(source, rgb);

然后使用RGB通道和Alpha通道创建RGBA图像:

Mat imgBGRA;

vector<Mat> channels = {rgb[0], rgb[1], rgb[2], sourceMask};
merge(channels, imgBGRA);

由于您的掩码是使用抗锯齿技术创建的,因此上面创建的图像也将具有抗锯齿透明度。


不,但没有理由它不能工作。我基本上已经为你写好了所有的东西 - 你只需要很少的东西来测试它。 - Jeshua Lacock
这里的源是什么? - Pratap
我只有一个包含透明像素的图像输入,这是由Swift生成的,我已经将它发送到OpenCV。在这里,您的代码似乎需要两个输入图像UIImageToMat()。 - Pratap
可能会有许多不需要被触碰的白色或像素,因此该方法无法奏效。 - Pratap
你将会做同样的事情,但是只是在OpenCV中应用遮罩而不是使用Swift代码。你不再使用Swift代码创建带有遮罩的图像,而是只创建一个遮罩。然后你将该遮罩应用到你的图像中,在OpenCV中进行处理。 - Jeshua Lacock
显示剩余13条评论

-1

OpenCV可以使用Canny边缘检测器帮助您找到边缘。您可以参考此链接中的实现。

使用C++进行OpenCV的Canny边缘检测。

此外,在实际提问之前,我建议您先自行进行一些研究。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接