如何不使用numpy将Python代码转换为Java

时间:2019-06-05 09:06:23

标签: java android python arrays opencv

我在Python中有一个方法,该方法利用OpenCV从图像中删除背景。我希望相同的功能可以与android的OpenCV版本一起使用,但我似乎无法完全围绕数组的工作方式以及如何处理它们进行思考。

这是我到目前为止在Java中所拥有的:

private Bitmap GetForeground(Bitmap source){
        source = scale(source,300,300);
        Mat mask = Mat.zeros(source.getHeight(),source.getWidth(),CvType.CV_8U);
        Mat bgModel = Mat.zeros(1,65,CvType.CV_64F);
        Mat ftModel = Mat.zeros(1,65,CvType.CV_64F);
        int x = (int)Math.round(source.getWidth()*0.1);
        int y = (int)Math.round(source.getHeight()*0.1);
        int width = (int)Math.round(source.getWidth()*0.8);
        int height = (int)Math.round(source.getHeight()*0.8);
        Rect rect = new Rect(x,y, width,height);
        Mat sourceMat = new Mat();
        Utils.bitmapToMat(source, sourceMat);
        Imgproc.grabCut(sourceMat, mask, rect, bgModel, ftModel, 5, Imgproc.GC_INIT_WITH_RECT);

        int frameSize=sourceMat.rows()*sourceMat.cols();
        byte[] buffer= new byte[frameSize];
        mask.get(0,0,buffer);
        for (int i = 0; i < frameSize; i++) {
            if (buffer[i] == 2 || buffer[i] == 0){
                buffer[i] = 0;
            }else{
                buffer[i] = 1 ;
            }
        }

        byte[][] sourceArray = getMultiChannelArray(sourceMat);
        byte[][][] reshapedMask = ReshapeArray(buffer, sourceMat.rows(), sourceMat.cols());
        return source;
    }

    private byte[][][] ReshapeArray(byte[] arr, int rows, int cols){
        byte[][][] out = new byte[cols][rows][1];
        int index=0;

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                out[i][j][0] = arr[index];
                index++;
            }
        }
        return out;
    }

    public static byte[][] getMultiChannelArray(Mat m) {
        //first index is pixel, second index is channel
        int numChannels=m.channels();//is 3 for 8UC3 (e.g. RGB)
        int frameSize=m.rows()*m.cols();
        byte[] byteBuffer= new byte[frameSize*numChannels];
        m.get(0,0,byteBuffer);

        //write to separate R,G,B arrays
        byte[][] out=new byte[frameSize][numChannels];
        for (int p=0,i = 0; p < frameSize; p++) {
            for (int n = 0; n < numChannels; n++,i++) {
                out[p][n]=byteBuffer[i];
            }
        }
        return out;
    }

我要重新创建的python代码:

image = cv2.imread('Images/handheld.jpg')
image = imutils.resize(image, height = 300)
mask = np.zeros(image.shape[:2],np.uint8)
bgModel = np.zeros((1,65),np.float64)
frModel = np.zeros((1,65),np.float64)
height, width, d = np.array(image).shape
rect = (int(width*0.1),int(height*0.1),int(width*0.8),int(height*0.8))
cv2.grabCut(image, mask, rect, bgModel,frModel, 5,cv2.GC_INIT_WITH_RECT)
mask = np.where((mask==2) | (mask == 0),0,1).astype('uint8')
image = image*mask[:,:,np.newaxis]

我不知道如何转换python代码的最后两行。如果有一种方法可以在我自己的项目中的android设备上运行python clean,那也很棒。

2 个答案:

答案 0 :(得分:0)

此时,您应该考虑与SL4A项目进行一下交流,这将使您可以通过Java应用程序在Android上运行Python代码。

以下是有趣的链接:

  1. https://github.com/damonkohler/sl4a

  2. https://norwied.wordpress.com/2012/04/11/run-sl4a-python-script-from-within-android-app/

  3. http://jokar-johnk.blogspot.com/2011/02/how-to-make-android-app-with-sl4a.html

答案 1 :(得分:0)

让我们看一下这两个命令,并尝试将它们转换为Java API调用。这可能不是简单的两行代码。

object Form1: TForm1 ... object PanelDialogo1: TPanelDialogo ... object PanelDialogo1_Label2: TLabel Caption = 'Another label right here' end object PanelDialogo1_Label1: TLabel Caption = 'A label in the top of the panel' end object PanelDialogo1_Edit1: TEdit Text = 'Write something here...' end object PanelDialogo1_Panel1: TPanel object PanelDialogo1_Button1: TButton Caption = 'OK' end end object PanelDialogo1_Label3: TLabel Caption = 'Some label just here' end end end

在上述命令中,我们正在创建一个新图像mask = np.where((mask==2) | (mask == 0),0,1).astype('uint8'),该图像的像素值的数据类型为mask。对于新的uint矩阵,对于每个位置,其中先前的mask的值为0mask,否则为2,其值将为0。让我们用一个例子来证明这一点:

1

此操作后的输出为:

mask = [
[0, 1, 1, 2],
[1, 0, 1, 3],
[0, 1, 1, 2],
[2, 3, 1, 0],
]

因此,以上命令只是生成仅包含0和1值的二进制掩码。可以使用mask = [ [0, 1, 1, 0], [1, 0, 1, 1], [0, 1, 1, 0], [0, 1, 1, 0], ] 方法在Java中复制此文件:

Core.compare()

现在,您需要将此前景蒙版与输入图像相乘,以获得最终的抓取图像,如下所示:

// Get a mask for all `1` values in matrix.
Mat mask1vals;
Core.compare(mask, new Scalar(1), mask1vals, Core.CMP_EQ);

// Get a mask for all `3` values in matrix.
Mat mask3vals;
Core.compare(mask, new Scalar(3), mask3vals, Core.CMP_EQ);

// Create a combined mask
Mat foregroundMask;
Core.max(mask1vals, mask3vals, foregroundMask)