2017-03-22 11 views
11

próbuję tłumaczyć następujących funkcji Python, że zastosowanie maski do obrazu, w Javie:Przekłada funkcji Pythona zastosować maskę do obrazu w Javie

# 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 

Jak dotąd, jest to, co ja” dostałem:

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; 
} 

Ale to nie działa. Kiedy próbuję wywoływanie tej metody, jak w poniższym przykładzie:

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); 

(Zakładam, że jest to właściwy sposób na zbudowanie macierzy 2x3 trzech punktów z dwóch współrzędnych każdy (1,2), (3, 4) i (5,6))

uzyskać wyjątek:

java.lang.RuntimeException: std::bad_alloc 
at org.bytedeco.javacpp.opencv_imgproc.fillPoly(Native Method) 

używam OpenCV przewidziane przez org.bytedeco.javacpp-presets:opencv-platform:3.2.0-1.3 poprzez Maven Central.

Muszę przyznać, że brakuje mi tutaj: jaki jest idiomatyczny sposób Java, który robi to samo, co powyższa funkcja Pythona?

+0

Myślę, że to, czego szukasz, jest związane z tym innym stackoverflow post http: // stackoverflow.com/questions/221830/set-bufferedimage-alpha-mask-in-java. Mam nadzieję, że to może pomóc. –

+0

W jaki sposób inicjujesz zmienną src, którą wysyłasz do applyMask? – Daedalus

+0

Jedna podejrzana rzecz polega na tym, że najwyraźniej definiujesz kolor dla obrazu 3-kanałowego z 12 kolorami. To nie może być prawda. – Dave

Odpowiedz

1

Może jakiś świr ma pełne odpowiedzi. Oto do myślenia:

  1. Java API jest bezpośrednią kopią API CPP: http://opencv.org/opencv-java-api.html
  2. Błąd std::bad_alloc występuje, gdy nie uda się przydzielić wymaganej przestrzeni dyskowej. (http://answers.opencv.org/question/28959/cascade-training-killed-and-bad_alloc/)

  3. Istnieją dwie metody CPP:
  4. Nie trzeba przekonwertować z Mat do InputArray, ale możesz (i powinieneś) po prostu przekazać obiekt Mat gdzie InputArray jest wymagane (https://stackoverflow.com/a/32976883/1587329)

+0

Dziękuję za rozpatrzenie tego, ale to nie pomaga. Żadna z metod 'fillPoly' widocznych po stronie Java nie przyjmuje' InputArray'. Biorą "Mat" lub "UMat". Myślę, że mój problem polega raczej na tym, że nie zdefiniowałem właściwie listy punktów. Na przykład pomocne byłoby podanie przykładu tworzenia argumentów punktowych za pomocą, powiedzmy, listy 4 punktów, z 2 współrzędnymi każda. – zugaldia

+0

@Zugaldia: Dziękuję za opinię. Czy próbowałeś opcji pamięci, aby zwiększyć wielkość sterty, jak w f.ex. '-Xmx512m'? –

+0

Tak. Wydaje mi się, że wydaje się, że chcę użyć metody 'public static native void fillPoly (Mat blackImg, MatVector points, Scalar whiteColor);' ale nie definiuję poprawnie 'MatVector points'. Jak utworzyć nowy "MatVector" dla tego przypadku użycia? – zugaldia

1

porządku, w końcu zdobione. Jeśli zdefiniować współrzędne z:

int[] points = new int[] {x1, y1, x2, y2, ...}; 

Następnie można po prostu zastosować maskę z następującego kodu:

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); 

Gdzie image jest oryginalny obraz, a masked jest zamaskowany wynik.

Problem polegał na tym, że oryginalna lista punktów nie została poprawnie zdefiniowana.

Powiązane problemy