You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Kotlin Multiplatform共享模块集成Chaquopy 16.0无法访问Python,求解决.pkl文件处理及Numpy使用问题

在Kotlin Multiplatform共享模块集成Chaquopy 16.0无法访问Python,求解决.pkl文件处理及Numpy使用问题

我正在开发一个Kotlin Multiplatform应用,想在共享模块里借助Numpy来处理.pkl文件。我跟着Chaquopy的官方配置步骤做了设置,但目前遇到了一些问题,具体情况如下:

一、我的配置文件

1. 项目根目录 settings.gradle.kts

rootProject.name = "Assignment"
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")

pluginManagement {
    repositories {
        google {
            mavenContent {
                includeGroupAndSubgroups("androidx")
                includeGroupAndSubgroups("com.android")
                includeGroupAndSubgroups("com.google")

            }
        }

        mavenCentral()
        gradlePluginPortal()
    }
}

dependencyResolutionManagement {
    repositories {
        google {
            mavenContent {
                includeGroupAndSubgroups("androidx")
                includeGroupAndSubgroups("com.android")
                includeGroupAndSubgroups("com.google")
            }
        }
        mavenCentral()
    }
}

include(":composeApp")
include(":shared")

2. 项目根目录 build.gradle.kts

plugins {
    // this is necessary to avoid the plugins to be loaded multiple times
    // in each subproject's classloader
    alias(libs.plugins.androidApplication) apply false
    alias(libs.plugins.androidLibrary) apply false
    alias(libs.plugins.composeMultiplatform) apply false
    alias(libs.plugins.composeCompiler) apply false
    alias(libs.plugins.kotlinMultiplatform) apply false
    id("com.chaquo.python") version "16.0.0" apply false
}

3. 共享模块 shared/build.gradle.kts

import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.androidLibrary)
    id("com.chaquo.python")
}

kotlin {
    androidTarget {
        @OptIn(ExperimentalKotlinGradlePluginApi::class)
        compilerOptions {
            jvmTarget.set(JvmTarget.JVM_11)
        }
    }

    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64()
    ).forEach { iosTarget ->
        iosTarget.binaries.framework {
            baseName = "Shared"
            isStatic = true
        }
    }

    sourceSets {

        androidMain.dependencies {

        }
        iosMain.dependencies {

        }

        commonMain.dependencies {
            implementation(libs.multik.core)
            implementation(libs.multik.kotlin)

        }
    }
}

android {
    namespace = "com.assignment.shared"
    compileSdk = libs.versions.android.compileSdk.get().toInt()
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
    defaultConfig {
        minSdk = libs.versions.android.minSdk.get().toInt()
        ndk {
            // On Apple silicon, you can omit x86_64.
            abiFilters += listOf("arm64-v8a")
        }
    }
}
chaquopy {
    defaultConfig {
        buildPython ("/usr/local/bin/python3")
    }
    productFlavors { }
    sourceSets { }
}

二、遇到的问题

  • 首先出现了这个警告:
    Warning: Failed to compile to .pyc format: [/usr/local/bin/python3] does not appear to be a valid Python command.
    
    但我在终端里直接运行python3是完全正常的。
  • 尝试在共享模块的类中导入Python相关内容,但根本无法导入。

三、额外求助方向

如果有其他合适的库或者方案,能在KMM项目(同时支持iOS和Android)里处理.pkl文件,或者能帮我把下面的Python脚本转换成Kotlin/Multik代码,也非常感谢:

# -*- coding: utf-8 -*-

import numpy as np
import pickle


def seg_stride(sig, dz, f_start, est_t):
    """! Estimate stride start and end for walking segment

    @param sig Moving standard deviation of heel
    @param dz Depth difference between heels
    @param f_start Start frame of walking segment
    @param est_t Estimated duration of one stride
    @return fp_lr Estimated frames for stride [start, end]
    """
    cur_len = len(sig)
    m_thres = np.mean(sig[sig < np.median(sig)]) # get the mean for values less than median
    [idx] = np.where(np.diff((sig < m_thres) * 1) > 0) # the search start point for each stride, where the heel z goes below threshold
    
    # Filter idx such that there is only one in each stride
    # upward zero-crossings to nearest time step
    [upcross] = np.where((dz[:-1] <= 0) & (dz[1:] > 0))
    # downward zero-crossings
    [downcross] = np.where((dz[:-1] >= 0) & (dz[1:] < 0))
    if len(upcross) >= len(downcross):
        cross = upcross
    else:
        cross = downcross
    cross = np.concatenate([[0], cross, [cur_len]])
    filtered_idx = []

    # Iterate through the intervals in downcross
    for i in range(len(cross) - 1):
        start = cross[i]
        end = cross[i + 1]
        # Find elements in idx that are in the interval (start, end)
        elements_in_interval = idx[(idx >= start) & (idx < end)]
        # If there is exactly one element, keep it; otherwise, keep the smallest element
        if len(elements_in_interval) >= 1:
            filtered_idx.append(elements_in_interval[0])
    
    # Convert filtered_idx back to a numpy array
    filtered_idx = np.array(filtered_idx)

    num_fp = len(filtered_idx) # no. of strides

    if num_fp > 1:
        fp = np.zeros((num_fp))
        # refine and record the corresponding frame
        for k in range(num_fp):
            cur_t = filtered_idx[k]
            cur_sig = sig[cur_t : min(cur_len, cur_t + round(0.25 * est_t))] # search space for one stride, start point to 1/4 of estimated stride or end of vid

            # locate the local minimum
            s_idx = np.argmin(cur_sig)
            t2 = min(cur_len, cur_t + s_idx)
            t1 = max(0, cur_t - round(0.2 * est_t)) # what is this for?
            t_idx = np.argmax(dz[t1 : t2 + 1]) # checking step to see if there is an earlier peak?
            fp[k] = f_start + t1 + t_idx

        # set fp_left: each row is [start frame, end frame] of a valid stride
        fp_lr = np.zeros((num_fp - 1, 2), dtype=int)
        for k in range(num_fp - 1):
            fp_lr[k, 0] = int(fp[k])
            fp_lr[k, 1] = int(fp[k + 1])

    else:
        fp_lr = np.empty((0, 2), dtype=int)

    return fp_lr


def dist2plane_new(points, ground_plane):
    """! Project 3D points to plane and compute shortest distance

    @param points Input 3D points
    @param ground_plane ground plane parameters (a,b,c,d)
    @return projected_points Projected points on ground plane
    @return distance Shortest distance between points and plane
    """

    a, b, c, d = ground_plane

    projected_points = []
    distance = []
    for point in points:
        s, u, v = point
        t = (d - a * s - b * u - c * v) / (a * a + b * b + c * c)

        # point closest to plane
        x = s + a * t
        y = u + b * t
        z = v + c * t

        dist = abs(a * s + b * u + c * z + d) / (np.sqrt(a * a + b * b + c * c))
        projected_points.append([x, y, z])
        distance.append(dist)

    return np.array(projected_points), np.array(distance)


def refine_stride_boundary(angle, foot_on, cur_t, c_margin, nb_frames):
    # set local segment
    t1 = max(0, cur_t - c_margin)
    t2 = min(nb_frames - 1, cur_t + c_margin)

    # refine the start of stride by finding the  largest decrease in heel angle
    idx = local_argmin_diff(angle, t1, t2)
    t = t1 + idx

    # further refine by ensuring foot is on ground at t
    if t not in foot_on:
        # if foot not on ground, adjust to next frame when foot is on ground
        next_foot_on = foot_on[(foot_on - t)>0]
        if len(next_foot_on)>0:
            t = next_foot_on[0]

    return t


def find_boundaries(fp, angle, angle_other, foot_on, est_t, nb_frames):
    c_margin = round(est_t / 10)
    t = [] 

    # refine stride boundaries (foot on)
    for k in range(len(fp)):
        # refine start and end of stride
        t_start = refine_stride_boundary(angle, foot_on, fp[k, 0], c_margin, nb_frames)
        t_end = refine_stride_boundary(angle, foot_on, fp[k, 1], c_margin, nb_frames)
    
        # find foot offs
        if t_end >= t_start+4: # if next foot on is at least 4 frames ahead
            # find foot off - min angle between start and end of stride
            t_fo = t_start + local_argmin(angle, t_start, t_end)
            # if current foot off is at least 2 frames ahead of start
            if t_fo >= t_start+2: 
                # find other foot off
                to_fo = t_start + local_argmin(angle_other, t_start, t_fo)
                t.append([t_start, to_fo, t_fo, t_end])

    return t


def combine_left_right(fp1, fp2):
    # foot ons
    t_strides = [t[0] for t in fp2] + [t[-1] for t in fp2]
    t_strides = sorted(set(t_strides))
    t_strides = np.array(t_strides)
    refined_fp = []
    for fp in fp1:
        other_foot_on = t_strides[(t_strides>fp[1]) & (t_strides<fp[2])]
        if len(other_foot_on) == 1:
            refined_fp.append([fp[0], fp[1], other_foot_on[0], fp[2], fp[3]])
    return np.array(refined_fp)


def params_est_lidar(pose_data, fp_walk_list, ground_plane):
    """! Estimate gait parameters based on 3D pose data by identifying corresponding timestamps

    @param pose_data 3D pose data (28 key points) for
    """
    # 注:原代码此处不完整,保留原样

备注:内容来源于stack exchange,提问作者Devendra Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 03:43:07