将Python函数转换为Java,以将掩码应用于图像

将Python函数转换为Java,以将掩码应用于图像,java,opencv,mask,Java,Opencv,Mask,我正在尝试将以下Python函数(将掩码应用于图像)转换为Java: #应用图像遮罩。 def感兴趣区域(img、顶点): #定义要开始的空白掩码 掩码=np.类零(img) #根据输入图像定义3通道或1通道颜色以填充遮罩 如果长度(图像形状)>2: 通道计数=图像形状[2]#即3或4,取决于您的图像 忽略遮罩颜色=(255,)*通道计数 其他: 忽略遮罩颜色=255 #使用填充颜色填充由“顶点”定义的多边形内的像素 cv2.fillPoly(遮罩、顶点、忽略遮罩颜色) #仅在遮罩像素不为零的情

我正在尝试将以下Python函数(将掩码应用于图像)转换为Java:

#应用图像遮罩。
def感兴趣区域(img、顶点):
#定义要开始的空白掩码
掩码=np.类零(img)
#根据输入图像定义3通道或1通道颜色以填充遮罩
如果长度(图像形状)>2:
通道计数=图像形状[2]#即3或4,取决于您的图像
忽略遮罩颜色=(255,)*通道计数
其他:
忽略遮罩颜色=255
#使用填充颜色填充由“顶点”定义的多边形内的像素
cv2.fillPoly(遮罩、顶点、忽略遮罩颜色)
#仅在遮罩像素不为零的情况下返回图像
蒙版图像=cv2.按位和(img,蒙版)
返回蒙版图像
到目前为止,我得到的是:

public static opencv_core.Mat applyMask(opencv_core.Mat image, opencv_core.MatVector vertices) {
  opencv_core.Mat mask = opencv_core.Mat.zeros(image.size(), opencv_core.CV_8U).asMat();

  opencv_core.Scalar color = new opencv_core.Scalar(image.channels()); // 3
  double[] colors = new double[] {
    255.0, 255.0, 255.0, 255.0,
    255.0, 255.0, 255.0, 255.0,
    255.0, 255.0, 255.0, 255.0};
  color.put(colors, 0, colors.length);

  opencv_imgproc.fillPoly(mask, vertices, color);

  opencv_core.Mat dst = new opencv_core.Mat();
  opencv_core.bitwise_and(image, mask, dst);
  return dst;
}
但是,它不起作用。当我尝试调用此方法时,如以下示例所示:

opencv_core.MatVector points = new opencv_core.MatVector(
  new opencv_core.Mat(2, 3, opencv_core.CV_32F, new IntPointer(1, 2, 3, 4, 5, 6))
);

opencv_core.MatVector vertices = new opencv_core.MatVector(points);
opencv_core.Mat masked = LaneManager.applyMask(src, vertices);
(我假设这是建立一个由三个点组成的2x3矩阵的正确方法,每个点有两个坐标
(1,2)
(3,4)
(5,6)

我得到一个例外:

java.lang.RuntimeException: std::bad_alloc
at org.bytedeco.javacpp.opencv_imgproc.fillPoly(Native Method)
我使用的OpenCV是由
org.bytedeco.javacpp预置提供的:OpenCV平台:3.2.0-1.3
通过Maven Central


我必须承认,我在这里有些不知所措:与上面的Python函数做相同事情的惯用Java方式是什么?

也许某个天才有完整的答案。以下是值得思考的问题:

  • Java API是CPP API的直接副本:
  • 当您未能分配所需的存储空间时,会出现错误
    std::bad_alloc
    。()

  • 有两种CPP方法:
    • C++:,和
    • C++:
  • 您不需要从
    Mat
    转换到
    InputArray
    ,但是您可以(并且应该)只传递一个
    Mat
    对象,其中请求了
    InputArray
    ()


  • 好吧,我终于明白了。如果使用以下方法定义坐标:

    int[] points = new int[] {x1, y1, x2, y2, ...};
    
    然后,您可以使用以下代码简单地应用掩码:

    opencv_core.Mat mask = new opencv_core.Mat(image.size(), image.type());
    
    // Array of polygons where each polygon is represented as an array of points
    opencv_core.Point polygon = new opencv_core.Point();
    polygon.put(points, 0, points.length);
    opencv_imgproc.fillPoly(mask, polygon, new int[] {points.length / 2}, 1, new opencv_core.Scalar(255, 255, 255, 0));
    
    opencv_core.Mat masked = new opencv_core.Mat(image.size(), image.type());
    opencv_core.bitwise_and(image, mask, masked);
    
    其中,
    image
    是原始图像,
    masked
    是屏蔽结果


    问题是原始的点列表没有正确定义。

    我想你要找的是与另一个stackoverflow帖子有关的。希望这能有所帮助。您如何初始化发送到applyMask的src变量?一个可疑的问题是,您显然是在为具有12个颜色分量的3通道图像定义颜色。这不可能是对的。@Daedalus我只是在调用
    opencv\u core.Mat src=opencv\u imgcodecs.imread(文件名)
    其中
    filename
    是带有文件路径的
    字符串。@Dave用
    opencv_core.Scalar color=new opencv_core.Scalar(255,255,255,0)替换颜色也不起作用,并给出相同的错误消息。感谢您对此进行调查,但这没有帮助。Java端公开的
    fillPoly
    方法没有一个采用
    InputArray
    。他们要么使用
    Mat
    UMat
    。我认为我的问题更多的是没有正确定义点列表。例如,如果您能给我一个如何创建points参数的示例,例如,一个包含4个点的列表,每个点有2个坐标,那将非常有帮助。@zugaldia:谢谢您的反馈。您是否尝试过使用内存选项来增加堆大小,如在f.ex中<代码>-Xmx512m
    ?是。我认为他们的问题是我想使用方法
    publicstatic原生voidfillpoly(matblackimg,MatVector points,scalarwhitecolor)但我没有正确定义
    拟向量点。我如何为这个用例创建一个新的
    MatVector