1

我为图像识别任务执行 python 代码,它工作得很好,但是当我使用 Chaquopy 将它实现到一个 android 应用程序中时它不起作用。这是因为 python 代码中的第一条指令旨在使用此指令 cap = cv2.videoCapture(0) 打开相机,而此指令在 android 设备上不起作用。我还在 androidManifest.xml 中添加了相机和存储权限这是我的 Java 代码:

public class MainActivity extends AppCompatActivity  {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (! Python.isStarted()) {
        Python.start(new AndroidPlatform(this));
    }

    Python py = Python.getInstance();
    PyObject pym =py.getModule("MyPythonClass");

}

这是python代码(类的名称是MyPythonClass.py):

import numpy as np
from skimage.transform import pyramid_gaussian
from imutils.object_detection import non_max_suppression
import imutils
from skimage.feature import hog
from sklearn.externals import joblib
from skimage import color
import matplotlib.pyplot as plt
import os
import glob
from imutils.video import VideoStream
from imutils.video import FPS
import numpy as np
import argparse
import time
import cv2

min_wdw_sz = [68, 124]
step_size = [10, 10]
orientations = 9
pixels_per_cell = [6, 6]
cells_per_block = [2, 2]
visualize = False
normalize = True

threshold = .3
clf = joblib.load(os.path.join('/storage/emulated/0/Download/', 'svm.model'))
def sliding_window(image, window_size, step_size):

    for y in range(0, image.shape[0], step_size[1]):
        for x in range(0, image.shape[1], step_size[0]):
            yield (x, y, image[y: y + window_size[1], x: x + window_size[0]])
webcam = cv2.VideoCapture (0)

# loop over the frames from the video stream
while True:

    ret, frame = webcam.read()

    im = imutils.resize(frame, width=min(300, frame.shape[1]))
    orig = im.copy()
    min_wdw_sz = (64, 128)
    step_size = (10, 10)
    downscale = 1.25
    #List to store the detections
    detections = []
    #The current scale of the image
    scale = 0

    for im_scaled in pyramid_gaussian(im, downscale = downscale):
        #The list contains detections at the current scale
        if im_scaled.shape[0] < min_wdw_sz[1] or im_scaled.shape[1] < min_wdw_sz[0]:
            break
        for (x, y, im_window) in sliding_window(im_scaled, min_wdw_sz, step_size):
            if im_window.shape[0] != min_wdw_sz[1] or im_window.shape[1] != min_wdw_sz[0]:
                continue
            im_window = color.rgb2gray(im_window)
            fd = hog(im_window, orientations, pixels_per_cell, cells_per_block, transform_sqrt=normalize)

            fd = fd.reshape(1, -1)
            pred = clf.predict(fd)

            if pred == 1:

                if clf.decision_function(fd) > 1:
                    detections.append((int(x * (downscale**scale)), int(y * (downscale**scale)), clf.decision_function(fd),
                                       int(min_wdw_sz[0] * (downscale**scale)),
                                       int(min_wdw_sz[1] * (downscale**scale))))



        scale += 1

    clone = im.copy()

    # loop over the detections
    for (x_tl, y_tl, _, w, h) in detections:
        cv2.rectangle(im, (x_tl, y_tl), (x_tl + w, y_tl + h), (0, 255, 0), thickness = 2)

    rects = np.array([[x, y, x + w, y + h] for (x, y, _, w, h) in detections])
    sc = [score[0] for (x, y, score, w, h) in detections]

    sc = np.array(sc)
    pick = non_max_suppression(rects, probs = sc, overlapThresh = 0.3)
    #  print "shape, ", pick.shape

    for(xA, yA, xB, yB) in pick:
        cv2.rectangle(clone, (xA, yA), (xB, yB), (0, 45, 255), 2)



    # show the output frame
    cv2.imshow("Frame", clone)

这就是 logact 显示的错误:

 java.lang.RuntimeException: Unable to start activity ComponentInfo{com........MainActivity}: com.chaquo.python.PyException: AttributeError: 'NoneType' object has no attribute 'shape'
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3319)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3415)
        at android.app.ActivityThread.access$1100(ActivityThread.java:229)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1821)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:7325)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
     Caused by: com.chaquo.python.PyException: AttributeError: 'NoneType' object has no attribute 'shape'
        at <python>.<module>(/android_asset/chaquopy/app.zip/MyPythonClass.py:44)

编辑 :

在手机中授予权限(存储和摄像头)。和: minSdkVersion 19 targetSdkVersion 28 compileSdkVersion 28

4

1 回答 1

1

我认为 OpenCV 对原生 Android 相机 API 有一些支持,但它显然在当前的 Chaquopy 版本中不起作用。正如您在其他问题中发现的那样,最简单的解决方法是在 Java 中捕获图像,然后将其作为字节数组传输到 Python。

于 2019-08-27T13:50:55.633 回答