Skip to content

Commit

Permalink
installer for full standalone executable now working.
Browse files Browse the repository at this point in the history
  • Loading branch information
carsonswope committed Sep 3, 2021
1 parent 19bda1d commit df44558
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 15 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ src/cpp_grouping/*.pyd
src/cpp_grouping/cpp_grouping.cpp

cuda_fatbin

installer/pyi_build
installer/pyi_temp
installer/*.exe
46 changes: 46 additions & 0 deletions installer/3d_bz.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# -*- mode: python ; coding: utf-8 -*-


block_cipher = None

SITE_PACKAGES = 'C:/Users/Carson/miniconda3/envs/env_3d_beats/Lib/site-packages/'
REPO_ROOT = 'C:/Users/Carson/code/hand_decision_trees'

a = Analysis([REPO_ROOT + '/src/3d_bz.py'],
pathex=[REPO_ROOT],
binaries=[ (SITE_PACKAGES + 'glfw/glfw3.dll', '.') ],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)

exe = EXE(pyz,
a.scripts,
[],
exclude_binaries=True,
name='3d_bz',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True,
disable_windowed_traceback=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None )
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='3d_bz')
30 changes: 30 additions & 0 deletions installer/build_all.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# run this to create an installer.
# you must already have precompiled fatbins, and declare the model / config / fatbins you want to include
# run this from the root of the repo. i.e. you should be running the command: ./installer/build_all.ps1

$pyi_build = './installer/pyi_build'
$pyi_temp = './installer/pyi_temp'

if (Test-Path $pyi_build) { Remove-Item -Recurse -Force $pyi_build }
if (Test-Path $pyi_temp) { Remove-Item -Recurse -Force $pyi_temp }

# use pyinstaller to assemble standalone binary (and many many DLLs and other libs)
pyinstaller --workpath $pyi_temp --distpath $pyi_build ./installer/3d_bz.spec

if (Test-Path $pyi_temp) { Remove-Item -Recurse -Force $pyi_temp }

# you need Inno Setup (6) installed to make the installer!

$model_dir = 'model'
$model_cfg = 'model/model_cfg.json'
$fatbin_dir = 'cuda_fatbin'

&'C:\Program Files (x86)\Inno Setup 6\ISCC.exe' `
make_windows_installer.iss `
/Dbuild_dir=$pyi_build/3d_bz `
/Dmodel_dir=$model_dir `
/Dmodel_cfg=$model_cfg `
/Dfatbin_dir=$fatbin_dir `
/DAPP_NAME=3d-beats `
/DAPP_VERSION=2.0 `
/Oinstaller
54 changes: 54 additions & 0 deletions make_windows_installer.iss
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define PUBLISHER "Carson Swope"
#define APP_EXE "3d_bz.exe"

[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{E8E83B0A-4C84-458C-BA7B-CAEF3B56768B}
AppName={#APP_NAME}
AppVersion={#APP_VERSION}
AppVerName={#APP_NAME} {#APP_VERSION}
AppCopyright=Copyright (C) 2021 Carson Swope
AppPublisher=Carson Swope
AppPublisherURL=https://www.3d-beats.com/
DefaultDirName={autopf}\{#APP_NAME}
DisableProgramGroupPage=yes
; Install for current user, not system-wide
PrivilegesRequired=lowest
OutputBaseFilename={#APP_NAME}-setup-{#APP_VERSION}
Compression=lzma
SolidCompression=yes
WizardStyle=modern
VersionInfoVersion={#APP_VERSION}

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Files]
Source: "{#build_dir}/*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
Source: "{#model_dir}/*"; DestDir: "{app}/{#model_dir}"; Flags: ignoreversion recursesubdirs
Source: "{#fatbin_dir}/*"; DestDir: "{app}/{#fatbin_dir}"; Flags: ignoreversion recursesubdirs
Source: "hand_config.json"; DestDir: "{app}"; Flags: ignoreversion

[Dirs]
Name: "{userappdata}\3d-beats"

[UninstallDelete]
Type: filesandordirs; Name: "{userappdata}\3d-beats"
Type: filesandordirs; Name: "{app}"

[Icons]
; Name: "{app}\{#APP_NAME}"; Filename: "{app}\{#APP_NAME}"
Name: "{app}\{#APP_NAME}"; Filename: "{app}\{#APP_EXE}"; \
Parameters: "-cfg {app}\{#model_cfg} --fatbin_in {app}\{#fatbin_dir}"
Name: "{autoprograms}\{#APP_NAME}"; Filename: "{app}\{#APP_EXE}"; \
Parameters: "-cfg {app}\{#model_cfg} --fatbin_in {app}\{#fatbin_dir}"
Name: "{autodesktop}\{#APP_NAME}"; Filename: "{app}\{#APP_EXE}"; \
Parameters: "-cfg {#model_cfg} --fatbin_in {#fatbin_dir}"; Tasks: desktopicon

20 changes: 10 additions & 10 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 3d Beats v2!
# 3d-beats

![Hand Classifier](rdf.gif)

Expand All @@ -8,9 +8,13 @@ Labeled training data is obtained by using skin paint to color various sections

To generate fingertip positions, the mean shift algorithm is used to find the center of each classification region. The original depth image is then sampled at the determined pixel, to find the height of each fingertip above the plane.

## Instructions for installation / development.
## Installation

Unfortunately, it's not very well packaged for easy distribution at the moment. To start, you will need:
Download the latest installer from the releases page.

## Instructions for local development

To set up your system for local development, you will need:

- [microsoft visual studio 2019](https://visualstudio.microsoft.com/downloads/) (2019). Unfortunately you have to download the whole thing just to get the compiler toolkit
- [cuda toolkit](https://developer.nvidia.com/cuda-11.3.0-download-archive?target_os=Windows&target_arch=x86_64) (11.3 ? Maybe other versions would work)
Expand Down Expand Up @@ -91,10 +95,6 @@ Okay, so now the real thing! The idea is that each fingertip and thumb is assign
- make new model. simpler 2-stage RDF architecture:
- 1. fingertip OR {rest of hand} OR {thumb tip?} (2-3 classes)
- 2. identify which fingertip (4-5 classes)
- make midi selection more robust, / UI
- distribution
- python w/ environment. pyinstaller?
- precompiled fatbins - WORKING
- custom package: cpp_grouping
- model files
- cuda/opengl cleanup errors in console
- make midi selection more robust / provide UI for it
- cuda/opengl cleanup errors in console
- clean up gui layout - sensible defaults so imgui.ini not necessary
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ PyOpenGL==3.1.5
pyrealsense2==2.44.0.3073
scipy==1.6.2
python-rtmidi==1.4.9
pyinstaller==4.5.1
2 changes: 0 additions & 2 deletions src/calibrated_plane.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ def get_mat(self):
def make(self, pts_gpu, img_dims, start_mat = None):

self.rand_generator.fill_uniform(self.rand_cu)
# self.rand_cpu = np.random.uniform((self.num_random_guesses, 32), dtype=np.float32)
# self.rand_cu.set(self.rand_cpu)
self.candidate_planes_cu.fill(np.float(0))

DIM_X = img_dims[0]
Expand Down
10 changes: 8 additions & 2 deletions src/decision_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import json
import numpy as np

from pathlib import Path
import os.path

import pycuda.gpuarray as cu_array
import pycuda.driver as cu

Expand Down Expand Up @@ -177,6 +180,8 @@ class LayeredDecisionForest():
@staticmethod
def load(config_filename, eval_dims):
cfg = json.loads(open(config_filename).read())
# models are loaded 1-by-1 from paths with parent directory as a root
cfg['root'] = os.path.join(*Path(config_filename).parts[0:-1])
return LayeredDecisionForest(cfg, eval_dims)

def __init__(self, cfg, eval_dims):
Expand All @@ -185,7 +190,8 @@ def __init__(self, cfg, eval_dims):
self.eval_dims = eval_dims # y,x !!
self.m = []
for l in cfg['layers']:
m = DecisionForest.load(l['model'])
# model path is relative to config file itself
m = DecisionForest.load(os.path.join(cfg['root'], l['model']))
if 'filter_model' in l and 'filter_model_class in l':
filter_model = l['filter_model']
filter_model_class = l['filter_model_class']
Expand All @@ -194,7 +200,7 @@ def __init__(self, cfg, eval_dims):
filter_model_class = None

self.m.append((m, filter_model, filter_model_class))
# self.m = [DecisionForest.load(m) for m in cfg['layers']]

self.num_models = len(self.m)

self.label_images = [GpuBuffer(eval_dims, dtype=np.uint16) for _ in range(self.num_models)]
Expand Down
3 changes: 2 additions & 1 deletion src/rs_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ def start_stream(args):
pipeline_wrapper = rs.pipeline_wrapper(pipeline)
pipeline_profile = config.resolve(pipeline_wrapper)
device = pipeline_profile.get_device()
# in the place where the original command was run, this file must be available
device_config_json = open('hand_config.json', 'r').read()
rs.rs400_advanced_mode(device).load_json(device_config_json)
device.first_depth_sensor().set_option(rs.option.depth_units, 0.0001)
config.enable_stream(rs.stream.depth, 848, 480, rs.format.z16, 90)

profile = pipeline.start(config)
if rs_bag:
profile.get_device().as_playback().set_real_time(False)
Expand Down

0 comments on commit df44558

Please sign in to comment.