2017-03-22 22 views
11

我试着翻译下面的Python功能,应用于口罩,图像,到Java:翻译Python函数来敷面膜图像转换成Java

# Applies an image mask. 
def region_of_interest(img, vertices): 
    #defining a blank mask to start with 
    mask = np.zeros_like(img) 

    #defining a 3 channel or 1 channel color to fill the mask with depending on the input image 
    if len(img.shape) > 2: 
     channel_count = img.shape[2] # i.e. 3 or 4 depending on your image 
     ignore_mask_color = (255,) * channel_count 
    else: 
     ignore_mask_color = 255 

    #filling pixels inside the polygon defined by "vertices" with the fill color  
    cv2.fillPoly(mask, vertices, ignore_mask_color) 

    #returning the image only where mask pixels are nonzero 
    masked_image = cv2.bitwise_and(img, mask) 
    return masked_image 

到目前为止,这是我” ve得到了:

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作为Maven的通过由中央提供org.bytedeco.javacpp-presets:opencv-platform:3.2.0-1.3

我必须承认我在这里感到茫然:与上面的Python函数做同样事情的惯用Java方法是什么?

+0

我认为你在找什么是与这个其他stackoverflow帖子http:// stackoverflow。COM /问题/ 221830 /设置的BufferedImage-α-面具式的Java。希望这可以帮助。 –

+0

你是如何初始化你发送到applyMask的src变量的? – Daedalus

+0

一个可疑的事情是,你显然正在为12通道色彩分量的3通道图像定义颜色。这是不对的。 – Dave

回答

1

也许一些高手有完整的答案。这里是深思:

  1. Java的API是CPP API直接拷贝:http://opencv.org/opencv-java-api.html
  2. 错误std::bad_alloc当你无法分配所需的存储空间出现。 (http://answers.opencv.org/question/28959/cascade-training-killed-and-bad_alloc/

  3. 有两种CPP方法:
  4. 你并不需要从Mat转换为InputArray,但您可以(也应该)只通过一个Mat对象,其中InputArray请求(https://stackoverflow.com/a/32976883/1587329

+0

谢谢您关注此问题,但这无济于事。在Java端暴露的'fillPoly'方法都没有使用'InputArray'。他们要么采取“垫子”或“UMat”。我认为我的问题更多的是没有正确定义点的列表。例如,如果你能给我一个例子,说明如何用4个点的列表创建点参数,每个点有2个坐标。 – zugaldia

+0

@ zugaldia:感谢您的反馈。你是否尝试过内存选项来增加堆大小,如f.ex. '-Xmx512m'? –

+0

是的。我认为他们的问题是我想使用'public static native fillPoly(Mat blackImg,MatVector points,Scalar whiteColor);'但我没有正确定义MatVector points。我如何为这个用例创建一个新的'MatVector'? – zugaldia

1

好吧,我终于想通了。如果你定义坐标:

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是屏蔽后的结果。

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