在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
相关产品推荐
相关产品推荐

