Перевести функцию 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
До сих пор это то, что у меня есть:
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-presets:opencv-platform:3.2.0-1.3
через Maven Central.
Я должен признать, что я в затруднении здесь: какой идиоматический Java-способ сделать то же самое, что и функция Python выше?
Ответы
Ответ 1
Возможно, у некоторых свистов есть полные ответы. Вот пища для размышлений:
- Java API - это прямая копия API CPP: http://opencv.org/opencv-java-api.html
-
Ошибка std::bad_alloc
возникает, когда вы не можете выделить необходимое пространство для хранения. (http://answers.opencv.org/question/28959/cascade-training-killed-and-bad_alloc/)
- Существует два метода CPP:
- С++:
void fillPoly(Mat& img, const Point** pts, const int* npts, int ncontours, const Scalar& color, int lineType=LINE_8, int shift=0, Point offset=Point() )
и
- С++:
void fillPoly(InputOutputArray img, InputArrayOfArrays pts, const Scalar& color, int lineType=LINE_8, int shift=0, Point offset=Point() )
-
Вам не нужно конвертировать из Mat
в InputArray
, но вы можете (и должны) просто передать объект Mat
, где запрашивается InputArray
(<а4 > )
Ответ 2
Хорошо, я, наконец, понял это. Если вы определяете свои координаты с помощью:
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
- замаскированный результат.
Проблема заключалась в том, что исходный список точек не был определен правильно.