Compare commits

...

8 Commits

Author SHA1 Message Date
b84c43a898 v2 working 2025-12-08 20:25:20 +01:00
4943a20c11 working 2025-11-28 15:36:57 +00:00
40dc5b3b59 working 2025-11-28 08:31:35 +00:00
310997a8dd working 2025-11-27 21:28:10 +01:00
d3063a6048 working 2025-09-10 19:59:07 +02:00
35e0f79b35 working 2025-09-10 19:56:21 +02:00
5ab222aee3 working 2025-09-10 19:51:05 +02:00
5560f6b2e6 working 2025-08-25 19:37:48 +02:00
45 changed files with 2331 additions and 1098 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
*.pth filter=lfs diff=lfs merge=lfs -text

7
.gitignore vendored
View File

@ -1,6 +1,9 @@
/mmdetection/
/mmpose/
/.ipynb_checkpoints/
/.gpu/
/.gpu-3d/
/.venv/
/.venv/
/venv/
*.mp4
yolo11*

13
.idea/JustTwerk.iml generated
View File

@ -2,13 +2,20 @@
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gpu" />
<excludeFolder url="file://$MODULE_DIR$/.gpu-3d" />
<excludeFolder url="file://$MODULE_DIR$/.venv" />
<excludeFolder url="file://$MODULE_DIR$/.venv1" />
<excludeFolder url="file://$MODULE_DIR$/.venv-2" />
<excludeFolder url="file://$MODULE_DIR$/.venv3.10" />
</content>
<orderEntry type="jdk" jdkName="Python 3.10 (JustTwerk)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="GOOGLE" />
<option name="myDocStringFormat" value="Google" />
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
<component name="TestRunnerService">
<option name="PROJECT_TEST_RUNNER" value="py.test" />
</component>
</module>

2
.idea/misc.xml generated
View File

@ -3,5 +3,5 @@
<component name="Black">
<option name="sdkName" value="Python 3.13 (JustTwerk)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 virtualenv at C:\Users\Kajetan\PycharmProjects\JustTwerk\.gpu-3d" project-jdk-type="Python SDK" />
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (JustTwerk)" project-jdk-type="Python SDK" />
</project>

2
.idea/vcs.xml generated
View File

@ -2,7 +2,5 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/mmdetection" vcs="Git" />
<mapping directory="$PROJECT_DIR$/mmpose" vcs="Git" />
</component>
</project>

254
.idea/workspace.xml generated
View File

@ -4,23 +4,31 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="441a4e7b-d6ce-44cb-92c5-2f22f1b1874f" name="Changes" comment="initial commit">
<change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/JustTwerk.iml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/inspectionProfiles/profiles_settings.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/02_whole_body_from_image.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/body3d.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/hrnet_w48_coco_256x192-b9e0b3ab_20200708.pth" afterDir="false" />
<change afterPath="$PROJECT_DIR$/humanPoseDetection.ipynb" afterDir="false" />
<change afterPath="$PROJECT_DIR$/is_torch.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/rtmdet_m_8xb32-100e_coco-obj365-person-235e8209.pth" afterDir="false" />
<change afterPath="$PROJECT_DIR$/rtmpose-m_simcc-body7_pt-body7_420e-256x192-e48f03d0_20230504.pth" afterDir="false" />
<change afterPath="$PROJECT_DIR$/test.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/videopose_h36m_243frames_fullconv_supervised_cpn_ft-88f5abbb_20210527.pth" afterDir="false" />
<change beforePath="$PROJECT_DIR$/mmpose/demo/body3d_pose_lifter_demo.py" beforeDir="false" afterPath="$PROJECT_DIR$/mmpose/demo/body3d_pose_lifter_demo.py" afterDir="false" />
<list default="true" id="441a4e7b-d6ce-44cb-92c5-2f22f1b1874f" name="Changes" comment="working">
<change afterPath="$PROJECT_DIR$/3cams_3D_v2.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/3cams_3d.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/3ddisplay_replay.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/3ddisplay_replay_smoothed.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/audio.wav" afterDir="false" />
<change afterPath="$PROJECT_DIR$/calib_relative_to_A_3cams.npz" afterDir="false" />
<change afterPath="$PROJECT_DIR$/calibration_3cams.npz" afterDir="false" />
<change afterPath="$PROJECT_DIR$/calibration_3cams_2.npz" afterDir="false" />
<change afterPath="$PROJECT_DIR$/checkpoint/pretrained_h36m_detectron_coco.bin" afterDir="false" />
<change afterPath="$PROJECT_DIR$/moves_dump_2.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/moves_videopose3d.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/poses.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/record.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/record_one_pose.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/record_video_pose.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/rotate.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/JustTwerk.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/JustTwerk.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/calculate.py" beforeDir="false" afterPath="$PROJECT_DIR$/calculate.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/moves.pkl" beforeDir="false" afterPath="$PROJECT_DIR$/moves.pkl" afterDir="false" />
<change beforePath="$PROJECT_DIR$/moves_3d_mp4.py" beforeDir="false" afterPath="$PROJECT_DIR$/moves_3d_mp4.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/moves_dump.py" beforeDir="false" afterPath="$PROJECT_DIR$/moves_dump.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -36,6 +44,7 @@
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
<option name="ROOT_SYNC" value="SYNC" />
</component>
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 6
@ -49,33 +58,129 @@
"keyToString": {
"ModuleVcsDetector.initialDetectionPerformed": "true",
"Python.02_whole_body_from_image.executor": "Run",
"Python.3cams_3D_v2.executor": "Run",
"Python.3cams_3d.executor": "Run",
"Python.3d.executor": "Run",
"Python.3ddisplay_replay.executor": "Run",
"Python.3ddisplay_replay_smoothed.executor": "Run",
"Python.body3d.executor": "Run",
"Python.body3d_pose_lifter_demo.executor": "Run",
"Python.calculate.executor": "Run",
"Python.checkpoint.executor": "Run",
"Python.draw.executor": "Run",
"Python.filter.executor": "Run",
"Python.is_torch.executor": "Run",
"Python.local_visualizer_3d.executor": "Run",
"Python.mac.executor": "Run",
"Python.main.executor": "Run",
"Python.moves_3d_mp4.executor": "Run",
"Python.moves_dump.executor": "Run",
"Python.moves_videopose3d.executor": "Run",
"Python.openpose.executor": "Run",
"Python.receive_images.executor": "Run",
"Python.receiver.executor": "Run",
"Python.record.executor": "Run",
"Python.record_one_pose.executor": "Run",
"Python.record_video_pose.executor": "Run",
"Python.rotate.executor": "Run",
"Python.sender.executor": "Run",
"Python.test.executor": "Run",
"Python.ultralytics-test.executor": "Run",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
"RunOnceActivity.git.unshallow": "true",
"git-widget-placeholder": "main",
"ignore.virus.scanning.warn.message": "true",
"last_opened_file_path": "C:/Users/Kajetan/PycharmProjects/JustTwerk",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "editor.preferences.fonts.default",
"settings.editor.selected.configurable": "preferences.pluginManager",
"vue.rearranger.settings.migration": "true"
}
}]]></component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\Kajetan\PycharmProjects\JustTwerk" />
<recent name="C:\Users\Kajetan\PycharmProjects\JustTwerk\checkpoints" />
</key>
<key name="MoveFile.RECENT_KEYS">
<recent name="C:\Users\Kajetan\PycharmProjects\JustTwerk\video" />
</key>
</component>
<component name="RunManager">
<component name="RunManager" selected="Python.main">
<configuration name="draw" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="JustTwerk" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/draw.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="main" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="JustTwerk" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/main.py" />
<option name="PARAMETERS" value="cam" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="record" type="PythonConfigurationType" factoryName="Python">
<module name="JustTwerk" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="SDK_NAME" value="Python 3.10 (JustTwerk)" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="record.py" />
<option name="PARAMETERS" value="cam" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="test" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="JustTwerk" />
<option name="ENV_FILES" value="" />
@ -99,8 +204,16 @@
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<list>
<item itemvalue="Python.record" />
<item itemvalue="Python.draw" />
<item itemvalue="Python.main" />
<item itemvalue="Python.test" />
</list>
<recent_temporary>
<list>
<item itemvalue="Python.main" />
<item itemvalue="Python.draw" />
<item itemvalue="Python.test" />
</list>
</recent_temporary>
@ -108,8 +221,8 @@
<component name="SharedIndexes">
<attachedChunks>
<set>
<option value="bundled-js-predefined-d6986cc7102b-e03c56caf84a-JavaScript-PY-252.23892.515" />
<option value="bundled-python-sdk-7e47963ff851-f0eec537fc84-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-252.23892.515" />
<option value="bundled-js-predefined-d6986cc7102b-3aa1da707db6-JavaScript-PY-252.27397.106" />
<option value="bundled-python-sdk-4e2b1448bda8-9a97661f3031-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-252.27397.106" />
</set>
</attachedChunks>
</component>
@ -124,8 +237,71 @@
<workItem from="1755884695519" duration="705000" />
<workItem from="1755885461444" duration="2686000" />
<workItem from="1755888180570" duration="3107000" />
<workItem from="1755891319108" duration="23374000" />
<workItem from="1755891319108" duration="33842000" />
<workItem from="1755974689137" duration="258000" />
<workItem from="1755974961407" duration="19035000" />
<workItem from="1756053672258" duration="16821000" />
<workItem from="1756216787734" duration="969000" />
<workItem from="1756632365037" duration="26000" />
<workItem from="1757522631129" duration="3558000" />
<workItem from="1764254526843" duration="634000" />
<workItem from="1764255184384" duration="6392000" />
<workItem from="1764353820246" duration="17882000" />
<workItem from="1764784804916" duration="7972000" />
<workItem from="1764880290552" duration="2878000" />
<workItem from="1764958893210" duration="34000" />
<workItem from="1765018411287" duration="71000" />
<workItem from="1765018505033" duration="53000" />
<workItem from="1765020107173" duration="1348000" />
<workItem from="1765025143997" duration="529000" />
<workItem from="1765027747129" duration="34000" />
<workItem from="1765030737128" duration="335000" />
<workItem from="1765111063348" duration="626000" />
<workItem from="1765127499247" duration="1482000" />
<workItem from="1765146209178" duration="2453000" />
<workItem from="1765209069862" duration="6395000" />
</task>
<task id="LOCAL-00001" summary="initial commit">
<option name="closed" value="true" />
<created>1755963464017</created>
<option name="number" value="00001" />
<option name="presentableId" value="LOCAL-00001" />
<option name="project" value="LOCAL" />
<updated>1755963464017</updated>
</task>
<task id="LOCAL-00002" summary="working">
<option name="closed" value="true" />
<created>1756143470328</created>
<option name="number" value="00002" />
<option name="presentableId" value="LOCAL-00002" />
<option name="project" value="LOCAL" />
<updated>1756143470328</updated>
</task>
<task id="LOCAL-00003" summary="working">
<option name="closed" value="true" />
<created>1757526666977</created>
<option name="number" value="00003" />
<option name="presentableId" value="LOCAL-00003" />
<option name="project" value="LOCAL" />
<updated>1757526666977</updated>
</task>
<task id="LOCAL-00004" summary="working">
<option name="closed" value="true" />
<created>1757526984452</created>
<option name="number" value="00004" />
<option name="presentableId" value="LOCAL-00004" />
<option name="project" value="LOCAL" />
<updated>1757526984452</updated>
</task>
<task id="LOCAL-00005" summary="working">
<option name="closed" value="true" />
<created>1757527150056</created>
<option name="number" value="00005" />
<option name="presentableId" value="LOCAL-00005" />
<option name="project" value="LOCAL" />
<updated>1757527150056</updated>
</task>
<option name="localTasksCounter" value="6" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@ -133,16 +309,38 @@
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="initial commit" />
<option name="LAST_COMMIT_MESSAGE" value="initial commit" />
<MESSAGE value="working" />
<option name="LAST_COMMIT_MESSAGE" value="working" />
</component>
<component name="com.intellij.coverage.CoverageDataManagerImpl">
<SUITE FILE_PATH="coverage/JustTwerk$openpose.coverage" NAME="openpose Coverage Results" MODIFIED="1755886110615" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/human-pose-estimation-opencv" />
<SUITE FILE_PATH="coverage/JustTwerk$body3d_pose_lifter_demo.coverage" NAME="body3d_pose_lifter_demo Coverage Results" MODIFIED="1755937235510" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/mmpose/demo" />
<SUITE FILE_PATH="coverage/JustTwerk$checkpoint.coverage" NAME="checkpoint Coverage Results" MODIFIED="1755936916130" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/.gpu/Lib/site-packages/mmengine/runner" />
<SUITE FILE_PATH="coverage/JustTwerk$calculate.coverage" NAME="calculate Coverage Results" MODIFIED="1756054778057" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$moves_videopose3d.coverage" NAME="moves_videopose3d Coverage Results" MODIFIED="1764346738082" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$record_one_pose.coverage" NAME="record_one_pose Coverage Results" MODIFIED="1764350684205" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$3ddisplay_replay.coverage" NAME="3ddisplay_replay Coverage Results" MODIFIED="1765127528144" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$sender.coverage" NAME="sender Coverage Results" MODIFIED="1756142463914" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$openpose.coverage" NAME="openpose Coverage Results" MODIFIED="1755886110615" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/human-pose-estimation-opencv" />
<SUITE FILE_PATH="coverage/JustTwerk$draw.coverage" NAME="draw Coverage Results" MODIFIED="1756053706980" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$ultralytics_test.coverage" NAME="ultralytics-test Coverage Results" MODIFIED="1756116377896" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$3d.coverage" NAME="3d Coverage Results" MODIFIED="1756027604884" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$moves_dump.coverage" NAME="moves_dump Coverage Results" MODIFIED="1765111609135" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$local_visualizer_3d.coverage" NAME="local_visualizer_3d Coverage Results" MODIFIED="1755937454029" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/.gpu/Lib/site-packages/mmpose/visualization" />
<SUITE FILE_PATH="coverage/JustTwerk$3cams_3d.coverage" NAME="3cams_3d Coverage Results" MODIFIED="1765111273047" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$main.coverage" NAME="main Coverage Results" MODIFIED="1765220020573" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$receiver.coverage" NAME="receiver Coverage Results" MODIFIED="1756142451233" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$filter.coverage" NAME="filter Coverage Results" MODIFIED="1755972211046" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$record.coverage" NAME="record Coverage Results" MODIFIED="1764350881825" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
<SUITE FILE_PATH="coverage/JustTwerk$moves_3d_mp4.coverage" NAME="moves_3d_mp4 Coverage Results" MODIFIED="1764352975374" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$body3d.coverage" NAME="body3d Coverage Results" MODIFIED="1755944498141" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$02_whole_body_from_image.coverage" NAME="02_whole_body_from_image Coverage Results" MODIFIED="1755885569302" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$local_visualizer_3d.coverage" NAME="local_visualizer_3d Coverage Results" MODIFIED="1755937454029" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/.gpu/Lib/site-packages/mmpose/visualization" />
<SUITE FILE_PATH="coverage/JustTwerk$checkpoint.coverage" NAME="checkpoint Coverage Results" MODIFIED="1755936916130" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/.gpu/Lib/site-packages/mmengine/runner" />
<SUITE FILE_PATH="coverage/JustTwerk$is_torch.coverage" NAME="is_torch Coverage Results" MODIFIED="1755943611769" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$test.coverage" NAME="test Coverage Results" MODIFIED="1755962675907" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$3ddisplay_replay_smoothed.coverage" NAME="3ddisplay_replay_smoothed Coverage Results" MODIFIED="1764878813417" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$record_video_pose.coverage" NAME="record_video_pose Coverage Results" MODIFIED="1765215859591" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$receive_images.coverage" NAME="receive_images Coverage Results" MODIFIED="1755966230858" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$is_torch.coverage" NAME="is_torch Coverage Results" MODIFIED="1764256054151" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$rotate.coverage" NAME="rotate Coverage Results" MODIFIED="1764831290832" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$mac.coverage" NAME="mac Coverage Results" MODIFIED="1764919104935" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$3cams_3D_v2.coverage" NAME="3cams_3D_v2 Coverage Results" MODIFIED="1765111338220" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/JustTwerk$test.coverage" NAME="test Coverage Results" MODIFIED="1756025632346" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
</component>
</project>

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"liveServer.settings.port": 5501
}

View File

@ -1,70 +0,0 @@
# From Python
# It requires OpenCV installed for Python
import sys
import cv2
import os
from sys import platform
import argparse
try:
# Import Openpose (Windows/Ubuntu/OSX)
dir_path = r"C:\Users\Kajetan\Documents\openpose/python"
try:
# Change these variables to point to the correct folder (Release/x64 etc.)
sys.path.append(dir_path + '/../bin/python/openpose/Release');
os.environ['PATH'] = os.environ['PATH'] + ';' + dir_path + '/../x64/Release;' + dir_path + '/../bin;'
print(os.environ["PATH"])
import pyopenpose as op
except ImportError as e:
print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')
raise e
# Flags
parser = argparse.ArgumentParser()
parser.add_argument("--image_path", default="../examples/media/COCO_val2014_000000000241.jpg", help="Process an image. Read all standard formats (jpg, png, bmp, etc.).")
args = parser.parse_known_args()
# Custom Params (refer to include/openpose/flags.hpp for more parameters)
params = dict()
params["model_folder"] = "../models/"
params["face"] = True
params["hand"] = True
# Add others in path?
for i in range(0, len(args[1])):
curr_item = args[1][i]
if i != len(args[1])-1: next_item = args[1][i+1]
else: next_item = "1"
if "--" in curr_item and "--" in next_item:
key = curr_item.replace('-','')
if key not in params: params[key] = "1"
elif "--" in curr_item and "--" not in next_item:
key = curr_item.replace('-','')
if key not in params: params[key] = next_item
# Construct it from system arguments
# op.init_argv(args[1])
# oppython = op.OpenposePython()
# Starting OpenPose
opWrapper = op.WrapperPython()
opWrapper.configure(params)
opWrapper.start()
# Process Image
datum = op.Datum()
imageToProcess = cv2.imread(args[0].image_path)
datum.cvInputData = imageToProcess
opWrapper.emplaceAndPop(op.VectorDatum([datum]))
# Display Image
print("Body keypoints: \n" + str(datum.poseKeypoints))
print("Face keypoints: \n" + str(datum.faceKeypoints))
print("Left hand keypoints: \n" + str(datum.handKeypoints[0]))
print("Right hand keypoints: \n" + str(datum.handKeypoints[1]))
cv2.imshow("OpenPose 1.7.0 - Tutorial Python API", datum.cvOutputData)
cv2.waitKey(0)
except Exception as e:
print(e)
sys.exit(-1)

85
3cams_3D_v2.py Normal file
View File

@ -0,0 +1,85 @@
import glob
import numpy as np
import cv2
import tqdm
from ultralytics import YOLO
import matplotlib.pyplot as plt
# --- Wczytanie kalibracji ---
data = np.load("calib_relative_to_A_3cams.npz")
K_A, D_A = data["K_A"], data["D_A"]
K_B, D_B = data["K_B"], data["D_B"]
K_C, D_C = data["K_C"], data["D_C"]
R_AA, T_AA = data["R_AA"], data["T_AA"]
R_BA, T_BA = data["R_BA"], data["T_BA"]
R_CA, T_CA = data["R_CA"], data["T_CA"]
# reshape translacji
T_AA = T_AA.reshape(3,1)
T_BA = T_BA.reshape(3,1)
T_CA = T_CA.reshape(3,1)
# Kamera A = układ odniesienia
P_A = K_A @ np.hstack((np.eye(3), np.zeros((3,1))))
P_B = K_B @ np.hstack((R_BA, T_BA))
P_C = K_C @ np.hstack((R_CA, T_CA))
def triangulate_three_views(pA, pB, pC):
pA = pA.reshape(2,1)
pB = pB.reshape(2,1)
pC = pC.reshape(2,1)
XAB_h = cv2.triangulatePoints(P_A, P_B, pA, pB)
XAB = (XAB_h / XAB_h[3])[:3].reshape(3)
XAC_h = cv2.triangulatePoints(P_A, P_C, pA, pC)
XAC = (XAC_h / XAC_h[3])[:3].reshape(3)
return (XAB + XAC)/2
# --- YOLO Pose ---
model = YOLO("yolo11x-pose.pt")
skeleton = [
[0,1],[0,2],[1,3],[2,4],[0,5],[0,6],
[5,7],[7,9],[6,8],[8,10],[5,6],
[11,12],[12,14],[14,16],[11,13],[13,15]
]
points3DList = {}
frames = sorted(glob.glob("video/camA/*.jpg"), key=lambda f: int(__import__("re").search(r"\d+", f).group()))
for frame in tqdm.tqdm(frames):
name = frame.replace('video/camA\\',"")
imgA = cv2.imread(f"video/camA/{name}")
imgB = cv2.imread(f"video/camB/{name}")
imgC = cv2.imread(f"video/camC/{name}")
rA = model(imgA, verbose=False)[0]
rB = model(imgB, verbose=False)[0]
rC = model(imgC, verbose=False)[0]
if len(rA.keypoints.xy)==0: continue
if len(rB.keypoints.xy)==0: continue
if len(rC.keypoints.xy)==0: continue
kpA = rA.keypoints.xy[0].cpu().numpy()
kpB = rB.keypoints.xy[0].cpu().numpy()
kpC = rC.keypoints.xy[0].cpu().numpy()
pts = []
for i in range(kpA.shape[0]):
X = triangulate_three_views(kpA[i], kpB[i], kpC[i])
pts.append(X)
pts = np.array(pts)
points3DList[name] = pts
import pickle
with open("replay_tpose.pkl", "wb") as f:
pickle.dump(points3DList, f)

112
3cams_3d.py Normal file
View File

@ -0,0 +1,112 @@
import glob
import numpy as np
import cv2
from ultralytics import YOLO
import matplotlib.pyplot as plt
# --- Wczytanie kalibracji ---
data = np.load("calibration_3cams_1.npz")
K1, D1 = data["K1"], data["D1"]
K2, D2 = data["K2"], data["D2"]
K3, D3 = data["K3"], data["D3"]
R12, T12 = data["R12"], data["T12"]
R13, T13 = data["R13"], data["T13"]
# Naprawa wymiarów translacji
T12 = T12.reshape(3,1)
T13 = T13.reshape(3,1)
# Kamera 1 = układ odniesienia
P1 = K1 @ np.hstack((np.eye(3), np.zeros((3,1))))
P2 = K2 @ np.hstack((R12, T12))
P3 = K3 @ np.hstack((R13, T13))
# --- Funkcja triangulacji 3D z trzech kamer ---
def triangulate_three_views(p1, p2, p3):
"""
Triangulacja 3D z trzech kamer metodą OpenCV + średnia dla stabilności
p1, p2, p3: punkty w pikselach (2,)
"""
# Zamiana na odpowiedni kształt (2,1)
p1 = p1.reshape(2,1)
p2 = p2.reshape(2,1)
p3 = p3.reshape(2,1)
# Triangulacja pary kamer 1-2
X12_h = cv2.triangulatePoints(P1, P2, p1, p2)
X12 = (X12_h / X12_h[3])[:3].reshape(3)
# Triangulacja pary kamer 1-3
X13_h = cv2.triangulatePoints(P1, P3, p1, p3)
X13 = (X13_h / X13_h[3])[:3].reshape(3)
# Średnia dla większej stabilności
X_avg = (X12 + X13) / 2
return X_avg
# --- Wczytanie YOLOv11 Pose ---
model = YOLO("yolo11x-pose.pt")
skeleton = [
[0,1],[0,2],[1,3],[2,4],[0,5],[0,6],
[5,7],[7,9],[6,8],[8,10],[5,6],
[11,12],[12,14],[14,16],[11,13],[13,15]
]
plt.ion() # włączenie trybu interaktywnego
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# Tworzymy początkowy wykres punktów
points_plot = ax.scatter([], [], [], c='r', marker='o', s=50)
lines_plot = [ax.plot([0,0],[0,0],[0,0], c='b')[0] for _ in skeleton]
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.view_init(elev=20, azim=-60)
points3DList = {}
for i in sorted(glob.glob("video/camA/*.jpg"), key=lambda f: int(__import__("re").search(r"\d+", f).group())):
# Zakładamy, że mamy 3 obrazy z 3 kamer
data = i.replace(f'video/camA\\', "")
img1 = cv2.imread(f"video/camA/{data}")
img2 = cv2.imread(f"video/camB/{data}")
img3 = cv2.imread(f"video/camC/{data}")
# Predykcja keypoints
results1 = model(img1, verbose=False)[0]
results2 = model(img2, verbose=False)[0]
results3 = model(img3, verbose=False)[0]
# Zakładamy jedną osobę na scenie
if len(results1.keypoints.xy) == 0: continue
if len(results2.keypoints.xy) == 0: continue
if len(results3.keypoints.xy) == 0: continue
yolo_cam1 = results1.keypoints.xy[0].cpu().numpy() # shape (17,2)
yolo_cam2 = results2.keypoints.xy[0].cpu().numpy()
yolo_cam3 = results3.keypoints.xy[0].cpu().numpy()
# --- Triangulacja wszystkich punktów ---
points3D = []
for i in range(yolo_cam1.shape[0]): # 17 punktów COCO
p1 = yolo_cam1[i]
p2 = yolo_cam2[i]
p3 = yolo_cam3[i]
X = triangulate_three_views(p1, p2, p3)
points3D.append(X)
points3D = np.array(points3D)
print(points3D)
points3DList[data] = points3D
import pickle
with open("replay_tpose.pkl", "wb") as f:
pickle.dump(points3DList, f)

57
3ddisplay_replay.py Normal file
View File

@ -0,0 +1,57 @@
import pickle
from matplotlib import pyplot as plt
with open("replay_xyz.pkl", "rb") as f:
points3DList = pickle.load(f)
skeleton = [
[0, 1], [0, 2], # nose -> eyes
[1, 3], [2, 4], # eyes -> ears
# [0, 5], [0, 6], # nose -> shoulders
[5, 7], [7, 9], # left arm
[6, 8], [8, 10], # right arm
[5, 6], # shoulders
[5, 11], [6, 12], # shoulders -> hips
[11, 12], # hips
[11, 13], [13, 15], # left leg
[12, 14], [14, 16] # right leg
]
plt.ion() # włączenie trybu interaktywnego
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# Tworzymy początkowy wykres punktów
points_plot = ax.scatter([], [], [], c='r', marker='o', s=50)
lines_plot = [ax.plot([0,0],[0,0],[0,0], c='b')[0] for _ in skeleton]
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_xlim(-0.6, 0.4)
ax.set_ylim(1.2, 2.2)
ax.set_zlim(-0.5, 1.1)
ax.view_init(elev=20, azim=-60)
i = 0
for points3Dkey in points3DList:
points3D = points3DList[points3Dkey]
print("3D points:\n", points3D)
# --- Wizualizacja 3D ---d
X = points3D[:,0] - 0.25
Z = -points3D[:,1] + 0.5
Y = points3D[:,2]
points_plot._offsets3d = (X, Y, Z)
# Aktualizacja linii (szkielet)
for idx, (i, j) in enumerate(skeleton):
lines_plot[idx].set_data([X[i], X[j]], [Y[i], Y[j]])
lines_plot[idx].set_3d_properties([Z[i], Z[j]])
fig.canvas.draw()
fig.canvas.flush_events()
plt.pause(0.01)

View File

@ -0,0 +1,58 @@
from scipy.signal import savgol_filter
import numpy as np
import pickle
from matplotlib import pyplot as plt
with open("replay_xyz.pkl", "rb") as f:
points3DList = pickle.load(f)
skeleton = [
[0, 1], [0, 2],
[1, 3], [2, 4],
[5, 7], [7, 9],
[6, 8], [8, 10],
[5, 6],
[5, 11], [6, 12],
[11, 12],
[11, 13], [13, 15],
[12, 14], [14, 16]
]
keys_sorted = sorted(points3DList.keys())
points_sequence = np.array([points3DList[k] for k in keys_sorted]) # (frames, points, 3)
# --- Filtr Savitzky-Golaya ---
window_length = 7 # musi być nieparzyste
polyorder = 2
smoothed_sequence = savgol_filter(points_sequence, window_length=window_length,
polyorder=polyorder, axis=0, mode='nearest')
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
points_plot = ax.scatter([], [], [], c='r', marker='o', s=50)
lines_plot = [ax.plot([0,0],[0,0],[0,0], c='b')[0] for _ in skeleton]
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_xlim(-0.6, 0.4)
ax.set_ylim(1.2, 2.2)
ax.set_zlim(-0.5, 1.1)
ax.view_init(elev=20, azim=-60)
for frame_points in smoothed_sequence:
X = frame_points[:,0] - 0.25
Z = -frame_points[:,1] + 0.5
Y = frame_points[:,2]
points_plot._offsets3d = (X, Y, Z)
for idx, (i, j) in enumerate(skeleton):
lines_plot[idx].set_data([X[i], X[j]], [Y[i], Y[j]])
lines_plot[idx].set_3d_properties([Z[i], Z[j]])
fig.canvas.draw()
fig.canvas.flush_events()
plt.pause(0.001)

Binary file not shown.

Binary file not shown.

Binary file not shown.

555
body3d.py
View File

@ -1,555 +0,0 @@
# Copyright (c) OpenMMLab. All rights reserved.
import logging
import mimetypes
import os
import time
from argparse import ArgumentParser
from functools import partial
import cv2
import json_tricks as json
import mmcv
import mmengine
import numpy as np
from mmengine.logging import print_log
from mmpose.apis import (_track_by_iou, _track_by_oks,
convert_keypoint_definition, extract_pose_sequence,
inference_pose_lifter_model, inference_topdown,
init_model)
from mmpose.models.pose_estimators import PoseLifter
from mmpose.models.pose_estimators.topdown import TopdownPoseEstimator
from mmpose.registry import VISUALIZERS
from mmpose.structures import (PoseDataSample, merge_data_samples,
split_instances)
from mmpose.utils import adapt_mmdet_pipeline
try:
from mmdet.apis import inference_detector, init_detector
has_mmdet = True
except (ImportError, ModuleNotFoundError):
has_mmdet = False
def parse_args():
parser = ArgumentParser()
parser.add_argument('--det_config', default="mmpose/demo/mmdetection_cfg/rtmdet_m_640-8xb32_coco-person.py", help='Config file for detection')
parser.add_argument('--det_checkpoint', default="rtmdet_m_8xb32-100e_coco-obj365-person-235e8209.pth", help='Checkpoint file for detection')
parser.add_argument(
'--pose_estimator_config',
type=str,
default="mmpose/configs/body_2d_keypoint/rtmpose/body8/rtmpose-m_8xb256-420e_body8-256x192.py",
help='Config file for the 1st stage 2D pose estimator')
parser.add_argument(
'--pose_estimator_checkpoint',
type=str,
default="rtmpose-m_simcc-body7_pt-body7_420e-256x192-e48f03d0_20230504.pth",
help='Checkpoint file for the 1st stage 2D pose estimator')
parser.add_argument(
'--pose_lifter_config',
default="mmpose/configs/body_3d_keypoint/video_pose_lift/h36m/video-pose-lift_tcn-243frm-supv-cpn-ft_8xb128-200e_h36m.py",
help='Config file for the 2nd stage pose lifter model')
parser.add_argument(
'--pose_lifter_checkpoint',
default="videopose_h36m_243frames_fullconv_supervised_cpn_ft-88f5abbb_20210527.pth",
help='Checkpoint file for the 2nd stage pose lifter model')
parser.add_argument('--input', type=str, default='webcam', help='Video path')
parser.add_argument(
'--show',
action='store_true',
default=True,
help='Whether to show visualizations')
parser.add_argument(
'--disable-rebase-keypoint',
action='store_true',
default=False,
help='Whether to disable rebasing the predicted 3D pose so its '
'lowest keypoint has a height of 0 (landing on the ground). Rebase '
'is useful for visualization when the model do not predict the '
'global position of the 3D pose.')
parser.add_argument(
'--disable-norm-pose-2d',
action='store_true',
default=False,
help='Whether to scale the bbox (along with the 2D pose) to the '
'average bbox scale of the dataset, and move the bbox (along with the '
'2D pose) to the average bbox center of the dataset. This is useful '
'when bbox is small, especially in multi-person scenarios.')
parser.add_argument(
'--num-instances',
type=int,
default=1,
help='The number of 3D poses to be visualized in every frame. If '
'less than 0, it will be set to the number of pose results in the '
'first frame.')
parser.add_argument(
'--output-root',
type=str,
default='',
help='Root of the output video file. '
'Default not saving the visualization video.')
parser.add_argument(
'--save-predictions',
action='store_true',
default=False,
help='Whether to save predicted results')
parser.add_argument(
'--device', default='cuda:0', help='Device used for inference')
parser.add_argument(
'--det-cat-id',
type=int,
default=0,
help='Category id for bounding box detection model')
parser.add_argument(
'--bbox-thr',
type=float,
default=0.3,
help='Bounding box score threshold')
parser.add_argument('--kpt-thr', type=float, default=0.3)
parser.add_argument(
'--use-oks-tracking', action='store_true', help='Using OKS tracking')
parser.add_argument(
'--tracking-thr', type=float, default=0.3, help='Tracking threshold')
parser.add_argument(
'--show-interval', type=int, default=0, help='Sleep seconds per frame')
parser.add_argument(
'--thickness',
type=int,
default=1,
help='Link thickness for visualization')
parser.add_argument(
'--radius',
type=int,
default=3,
help='Keypoint radius for visualization')
parser.add_argument(
'--online',
action='store_true',
default=False,
help='Inference mode. If set to True, can not use future frame'
'information when using multi frames for inference in the 2D pose'
'detection stage. Default: False.')
args = parser.parse_args()
return args
def process_one_image(args, detector, frame, frame_idx, pose_estimator,
pose_est_results_last, pose_est_results_list, next_id,
pose_lifter, visualize_frame, visualizer):
"""Visualize detected and predicted keypoints of one image.
Pipeline of this function:
frame
|
V
+-----------------+
| detector |
+-----------------+
| det_result
V
+-----------------+
| pose_estimator |
+-----------------+
| pose_est_results
V
+--------------------------------------------+
| convert 2d kpts into pose-lifting format |
+--------------------------------------------+
| pose_est_results_list
V
+-----------------------+
| extract_pose_sequence |
+-----------------------+
| pose_seq_2d
V
+-------------+
| pose_lifter |
+-------------+
| pose_lift_results
V
+-----------------+
| post-processing |
+-----------------+
| pred_3d_data_samples
V
+------------+
| visualizer |
+------------+
Args:
args (Argument): Custom command-line arguments.
detector (mmdet.BaseDetector): The mmdet detector.
frame (np.ndarray): The image frame read from input image or video.
frame_idx (int): The index of current frame.
pose_estimator (TopdownPoseEstimator): The pose estimator for 2d pose.
pose_est_results_last (list(PoseDataSample)): The results of pose
estimation from the last frame for tracking instances.
pose_est_results_list (list(list(PoseDataSample))): The list of all
pose estimation results converted by
``convert_keypoint_definition`` from previous frames. In
pose-lifting stage it is used to obtain the 2d estimation sequence.
next_id (int): The next track id to be used.
pose_lifter (PoseLifter): The pose-lifter for estimating 3d pose.
visualize_frame (np.ndarray): The image for drawing the results on.
visualizer (Visualizer): The visualizer for visualizing the 2d and 3d
pose estimation results.
Returns:
pose_est_results (list(PoseDataSample)): The pose estimation result of
the current frame.
pose_est_results_list (list(list(PoseDataSample))): The list of all
converted pose estimation results until the current frame.
pred_3d_instances (InstanceData): The result of pose-lifting.
Specifically, the predicted keypoints and scores are saved at
``pred_3d_instances.keypoints`` and
``pred_3d_instances.keypoint_scores``.
next_id (int): The next track id to be used.
"""
pose_lift_dataset = pose_lifter.cfg.test_dataloader.dataset
pose_lift_dataset_name = pose_lifter.dataset_meta['dataset_name']
# First stage: conduct 2D pose detection in a Topdown manner
# use detector to obtain person bounding boxes
det_result = inference_detector(detector, frame)
pred_instance = det_result.pred_instances.cpu().numpy()
# filter out the person instances with category and bbox threshold
# e.g. 0 for person in COCO
bboxes = pred_instance.bboxes
bboxes = bboxes[np.logical_and(pred_instance.labels == args.det_cat_id,
pred_instance.scores > args.bbox_thr)]
# estimate pose results for current image
pose_est_results = inference_topdown(pose_estimator, frame, bboxes)
if args.use_oks_tracking:
_track = partial(_track_by_oks)
else:
_track = _track_by_iou
pose_det_dataset_name = pose_estimator.dataset_meta['dataset_name']
pose_est_results_converted = []
# convert 2d pose estimation results into the format for pose-lifting
# such as changing the keypoint order, flipping the keypoint, etc.
for i, data_sample in enumerate(pose_est_results):
pred_instances = data_sample.pred_instances.cpu().numpy()
keypoints = pred_instances.keypoints
# calculate area and bbox
if 'bboxes' in pred_instances:
areas = np.array([(bbox[2] - bbox[0]) * (bbox[3] - bbox[1])
for bbox in pred_instances.bboxes])
pose_est_results[i].pred_instances.set_field(areas, 'areas')
else:
areas, bboxes = [], []
for keypoint in keypoints:
xmin = np.min(keypoint[:, 0][keypoint[:, 0] > 0], initial=1e10)
xmax = np.max(keypoint[:, 0])
ymin = np.min(keypoint[:, 1][keypoint[:, 1] > 0], initial=1e10)
ymax = np.max(keypoint[:, 1])
areas.append((xmax - xmin) * (ymax - ymin))
bboxes.append([xmin, ymin, xmax, ymax])
pose_est_results[i].pred_instances.areas = np.array(areas)
pose_est_results[i].pred_instances.bboxes = np.array(bboxes)
# track id
track_id, pose_est_results_last, _ = _track(data_sample,
pose_est_results_last,
args.tracking_thr)
if track_id == -1:
if np.count_nonzero(keypoints[:, :, 1]) >= 3:
track_id = next_id
next_id += 1
else:
# If the number of keypoints detected is small,
# delete that person instance.
keypoints[:, :, 1] = -10
pose_est_results[i].pred_instances.set_field(
keypoints, 'keypoints')
pose_est_results[i].pred_instances.set_field(
pred_instances.bboxes * 0, 'bboxes')
pose_est_results[i].set_field(pred_instances, 'pred_instances')
track_id = -1
pose_est_results[i].set_field(track_id, 'track_id')
# convert keypoints for pose-lifting
pose_est_result_converted = PoseDataSample()
pose_est_result_converted.set_field(
pose_est_results[i].pred_instances.clone(), 'pred_instances')
pose_est_result_converted.set_field(
pose_est_results[i].gt_instances.clone(), 'gt_instances')
keypoints = convert_keypoint_definition(keypoints,
pose_det_dataset_name,
pose_lift_dataset_name)
pose_est_result_converted.pred_instances.set_field(
keypoints, 'keypoints')
pose_est_result_converted.set_field(pose_est_results[i].track_id,
'track_id')
pose_est_results_converted.append(pose_est_result_converted)
pose_est_results_list.append(pose_est_results_converted.copy())
# Second stage: Pose lifting
# extract and pad input pose2d sequence
pose_seq_2d = extract_pose_sequence(
pose_est_results_list,
frame_idx=frame_idx,
causal=pose_lift_dataset.get('causal', False),
seq_len=pose_lift_dataset.get('seq_len', 1),
step=pose_lift_dataset.get('seq_step', 1))
# conduct 2D-to-3D pose lifting
norm_pose_2d = not args.disable_norm_pose_2d
pose_lift_results = inference_pose_lifter_model(
pose_lifter,
pose_seq_2d,
image_size=visualize_frame.shape[:2],
norm_pose_2d=norm_pose_2d)
# post-processing
for idx, pose_lift_result in enumerate(pose_lift_results):
pose_lift_result.track_id = pose_est_results[idx].get('track_id', 1e4)
pred_instances = pose_lift_result.pred_instances
keypoints = pred_instances.keypoints
keypoint_scores = pred_instances.keypoint_scores
if keypoint_scores.ndim == 3:
keypoint_scores = np.squeeze(keypoint_scores, axis=1)
pose_lift_results[
idx].pred_instances.keypoint_scores = keypoint_scores
if keypoints.ndim == 4:
keypoints = np.squeeze(keypoints, axis=1)
keypoints = keypoints[..., [0, 2, 1]]
keypoints[..., 0] = -keypoints[..., 0]
keypoints[..., 2] = -keypoints[..., 2]
# rebase height (z-axis)
if not args.disable_rebase_keypoint:
keypoints[..., 2] -= np.min(
keypoints[..., 2], axis=-1, keepdims=True)
pose_lift_results[idx].pred_instances.keypoints = keypoints
pose_lift_results = sorted(
pose_lift_results, key=lambda x: x.get('track_id', 1e4))
pred_3d_data_samples = merge_data_samples(pose_lift_results)
det_data_sample = merge_data_samples(pose_est_results)
pred_3d_instances = pred_3d_data_samples.get('pred_instances', None)
if args.num_instances < 0:
args.num_instances = len(pose_lift_results)
# Visualization
if visualizer is not None:
visualizer.add_datasample(
'result',
visualize_frame,
data_sample=pred_3d_data_samples,
det_data_sample=det_data_sample,
draw_gt=False,
dataset_2d=pose_det_dataset_name,
dataset_3d=pose_lift_dataset_name,
show=args.show,
draw_bbox=True,
kpt_thr=args.kpt_thr,
num_instances=args.num_instances,
wait_time=args.show_interval)
return pose_est_results, pose_est_results_list, pred_3d_instances, next_id
def main():
assert has_mmdet, 'Please install mmdet to run the demo.'
args = parse_args()
assert args.show or (args.output_root != '')
assert args.input != ''
assert args.det_config is not None
assert args.det_checkpoint is not None
detector = init_detector(
args.det_config, args.det_checkpoint, device=args.device.lower())
detector.cfg = adapt_mmdet_pipeline(detector.cfg)
pose_estimator = init_model(
args.pose_estimator_config,
args.pose_estimator_checkpoint,
device=args.device.lower())
assert isinstance(pose_estimator, TopdownPoseEstimator), 'Only "TopDown"' \
'model is supported for the 1st stage (2D pose detection)'
det_kpt_color = pose_estimator.dataset_meta.get('keypoint_colors', None)
det_dataset_skeleton = pose_estimator.dataset_meta.get(
'skeleton_links', None)
det_dataset_link_color = pose_estimator.dataset_meta.get(
'skeleton_link_colors', None)
pose_lifter = init_model(
args.pose_lifter_config,
args.pose_lifter_checkpoint,
device=args.device.lower())
assert isinstance(pose_lifter, PoseLifter), \
'Only "PoseLifter" model is supported for the 2nd stage ' \
'(2D-to-3D lifting)'
pose_lifter.cfg.visualizer.radius = args.radius
pose_lifter.cfg.visualizer.line_width = args.thickness
pose_lifter.cfg.visualizer.det_kpt_color = det_kpt_color
pose_lifter.cfg.visualizer.det_dataset_skeleton = det_dataset_skeleton
pose_lifter.cfg.visualizer.det_dataset_link_color = det_dataset_link_color
visualizer = VISUALIZERS.build(pose_lifter.cfg.visualizer)
# the dataset_meta is loaded from the checkpoint
visualizer.set_dataset_meta(pose_lifter.dataset_meta)
if args.input == 'webcam':
input_type = 'webcam'
else:
input_type = mimetypes.guess_type(args.input)[0].split('/')[0]
if args.output_root == '':
save_output = False
else:
mmengine.mkdir_or_exist(args.output_root)
output_file = os.path.join(args.output_root,
os.path.basename(args.input))
if args.input == 'webcam':
output_file += '.mp4'
save_output = True
if args.save_predictions:
assert args.output_root != ''
args.pred_save_path = f'{args.output_root}/results_' \
f'{os.path.splitext(os.path.basename(args.input))[0]}.json'
if save_output:
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
pose_est_results_list = []
pred_instances_list = []
if input_type == 'image':
frame = mmcv.imread(args.input, channel_order='rgb')
_, _, pred_3d_instances, _ = process_one_image(
args=args,
detector=detector,
frame=frame,
frame_idx=0,
pose_estimator=pose_estimator,
pose_est_results_last=[],
pose_est_results_list=pose_est_results_list,
next_id=0,
pose_lifter=pose_lifter,
visualize_frame=frame,
visualizer=visualizer)
if args.save_predictions:
# save prediction results
pred_instances_list = split_instances(pred_3d_instances)
if save_output:
frame_vis = visualizer.get_image()
mmcv.imwrite(mmcv.rgb2bgr(frame_vis), output_file)
elif input_type in ['webcam', 'video']:
next_id = 0
pose_est_results = []
if args.input == 'webcam':
video = cv2.VideoCapture(0)
else:
video = cv2.VideoCapture(args.input)
(major_ver, minor_ver, subminor_ver) = (cv2.__version__).split('.')
if int(major_ver) < 3:
fps = video.get(cv2.cv.CV_CAP_PROP_FPS)
else:
fps = video.get(cv2.CAP_PROP_FPS)
video_writer = None
frame_idx = 0
while video.isOpened():
success, frame = video.read()
frame_idx += 1
if not success:
break
pose_est_results_last = pose_est_results
# First stage: 2D pose detection
# make person results for current image
(pose_est_results, pose_est_results_list, pred_3d_instances,
next_id) = process_one_image(
args=args,
detector=detector,
frame=frame,
frame_idx=frame_idx,
pose_estimator=pose_estimator,
pose_est_results_last=pose_est_results_last,
pose_est_results_list=pose_est_results_list,
next_id=next_id,
pose_lifter=pose_lifter,
visualize_frame=mmcv.bgr2rgb(frame),
visualizer=visualizer)
if args.save_predictions:
# save prediction results
pred_instances_list.append(
dict(
frame_id=frame_idx,
instances=split_instances(pred_3d_instances)))
if save_output:
frame_vis = visualizer.get_image()
if video_writer is None:
# the size of the image with visualization may vary
# depending on the presence of heatmaps
video_writer = cv2.VideoWriter(output_file, fourcc, fps,
(frame_vis.shape[1],
frame_vis.shape[0]))
video_writer.write(mmcv.rgb2bgr(frame_vis))
if args.show:
# press ESC to exit
if cv2.waitKey(5) & 0xFF == 27:
break
time.sleep(args.show_interval)
video.release()
if video_writer:
video_writer.release()
else:
args.save_predictions = False
raise ValueError(
f'file {os.path.basename(args.input)} has invalid format.')
if args.save_predictions:
with open(args.pred_save_path, 'w') as f:
json.dump(
dict(
meta_info=pose_lifter.dataset_meta,
instance_info=pred_instances_list),
f,
indent='\t')
print(f'predictions have been saved at {args.pred_save_path}')
if save_output:
input_type = input_type.replace('webcam', 'video')
print_log(
f'the output {input_type} has been saved at {output_file}',
logger='current',
level=logging.INFO)
if __name__ == '__main__':
main()

135
calculate.py Normal file
View File

@ -0,0 +1,135 @@
import numpy as np
import numpy as np
def angle_between(pkt1, pkt2, pkt3):
"""
Oblicza kąt między trzema punktami w stopniach z zachowaniem znaku.
pkt2 jest wierzchołkiem kąta.
Parameters:
pkt1, pkt2, pkt3 : array-like (x, y) lub (x, y, z)
Returns:
Kąt w stopniach (ujemny lub dodatni)
"""
pkt1 = np.array(pkt1[:2].cpu().numpy())
pkt2 = np.array(pkt2[:2].cpu().numpy())
pkt3 = np.array(pkt3[:2].cpu().numpy())
# wektory względem pkt2
a = pkt1 - pkt2
b = pkt3 - pkt2
# iloczyn skalarny i cosinus kąta
dot = np.dot(a, b)
norm = np.linalg.norm(a) * np.linalg.norm(b)
cos_theta = dot / norm
cos_theta = np.clip(cos_theta, -1.0, 1.0)
# kąt bez znaku
angle = np.degrees(np.arccos(cos_theta))
# znak z iloczynu wektorowego (w 2D to skalar = z-component)
cross = a[0]*b[1] - a[1]*b[0]
if cross < 0:
angle = -angle
return angle
def compare_poses(f1, f2):
# Odległość euklidesowa
l2_dist = np.linalg.norm(f1 - f2)
# Cosine similarity
cos_sim = np.dot(f1, f2) / (np.linalg.norm(f1) * np.linalg.norm(f2) + 1e-6)
return l2_dist, cos_sim
def compare_poses_boolean(f1, f2):
l2, cos_sim = compare_poses(f1, f2)
return l2 < 1.2 and cos_sim > 0.85
def center(keypoints):
mid_hip = (keypoints[11] + keypoints[12]) / 2 # left_hip=11, right_hip=12
keypoints = keypoints - mid_hip
return keypoints
def normalize_pose(keypoints):
"""
keypoints: np.array shape (17, 2) [x,y] dla COCO
Zwraca wektor cech odporny na skalę i przesunięcie
"""
# 1. translacja -> środek bioder jako początek układu
mid_hip = (keypoints[11] + keypoints[12]) / 2 # left_hip=11, right_hip=12
keypoints = keypoints - mid_hip
# 2. normalizacja skali -> odległość między barkami
shoulder_dist = np.linalg.norm(keypoints[5] - keypoints[6]) # left_shoulder=5, right_shoulder=6
if shoulder_dist > 0:
keypoints = keypoints / shoulder_dist
# 3. definicja segmentów (przykład: łokieć-ramię, nadgarstek-łokieć)
limbs = [
(5, 7), # ramię L
(7, 9), # przedramię L
(6, 8), # ramię P
(8, 10), # przedramię P
(11, 13), # udo L
(13, 15), # goleń L
(12, 14), # udo P
(14, 16), # goleń P
]
# 4. oblicz kąty
angles = []
for (a, b), (c, d) in zip(limbs[::2], limbs[1::2]): # np. (ramię, przedramię)
v1 = keypoints[b] - keypoints[a]
v2 = keypoints[d] - keypoints[c]
cos_angle = np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2) + 1e-6)
angle = np.arccos(np.clip(cos_angle, -1, 1))
angles.append(angle)
# 5. opcjonalnie: dodać wektory kończyn (znormalizowane)
vectors = []
for (a, b) in limbs:
v = keypoints[b] - keypoints[a]
v_norm = v / (np.linalg.norm(v) + 1e-6)
vectors.extend(v_norm)
# finalny wektor cech = kąty + wektory
feature_vector = np.concatenate([angles, vectors])
return feature_vector
def denormalize_pose(feature_vector):
"""
feature_vector: wynik normalize_pose
Zwraca przybliżone współrzędne keypoints (w układzie znormalizowanym)
"""
# 1. oddziel kąty i wektory
angles = feature_vector[:4]
vectors_flat = feature_vector[4:]
vectors = vectors_flat.reshape(-1, 2)
# 2. inicjalizacja keypoints
keypoints = np.zeros((17, 2))
# 3. przybliżona rekonstrukcja kończyn
limbs = [
(5, 7), (7, 9), (6, 8), (8, 10),
(11, 13), (13, 15), (12, 14), (14, 16)
]
for (a, b), v in zip(limbs, vectors):
keypoints[b] = keypoints[a] + v # przybliżona rekonstrukcja
# 4. punkt startowy (biodra) = (0,0), skalowanie w oryginale trzeba by przywrócić osobno
return keypoints

Binary file not shown.

185
draw.py Normal file

File diff suppressed because one or more lines are too long

93
filter.py Normal file
View File

@ -0,0 +1,93 @@
from collections import deque
import numpy as np
def filter_moves(moves):
newMoves = []
lastTime = 0
ema = EMAFilter(0.2)
for i, move in enumerate(moves):
s = move[0] / 1000
if i != len(moves) - 1:
origS = s
s = s - lastTime
lastTime = origS
newMoves.append((s, ema.update(move[1])))
return newMoves
class MedianFilter:
def __init__(self, n_channels=8, window_size=3):
self.n = n_channels
self.buffers = [deque(maxlen=window_size) for _ in range(n_channels)]
def update(self, angles_deg):
smoothed = []
for i, ang in enumerate(angles_deg):
self.buffers[i].append(ang)
smoothed_ang = np.median(self.buffers[i])
smoothed.append(smoothed_ang)
return smoothed
class HybridFilter:
def __init__(self, alpha=0.7, n_channels=8, median_window=3):
self.alpha = alpha
self.n = n_channels
self.median_window = median_window
# Bufory do mediany dla każdego kanału
self.buffers = [deque(maxlen=median_window) for _ in range(n_channels)]
# Stan EMA (cos/sin)
self.cos_state = [None] * n_channels
self.sin_state = [None] * n_channels
def update(self, angles_deg):
smoothed = []
for i, ang in enumerate(angles_deg):
# wrzucamy do bufora mediany
self.buffers[i].append(ang)
med = np.median(self.buffers[i]) # filtr medianowy
ang_rad = np.deg2rad(med)
c, s = np.cos(ang_rad), np.sin(ang_rad)
if self.cos_state[i] is None:
self.cos_state[i] = c
self.sin_state[i] = s
else:
self.cos_state[i] = self.alpha * c + (1 - self.alpha) * self.cos_state[i]
self.sin_state[i] = self.alpha * s + (1 - self.alpha) * self.sin_state[i]
smoothed_ang = np.rad2deg(np.arctan2(self.sin_state[i], self.cos_state[i]))
smoothed.append(smoothed_ang)
return smoothed
class EMAFilter:
def __init__(self, alpha=0.2, n_channels=8):
self.alpha = alpha
self.cos_state = [None] * n_channels
self.sin_state = [None] * n_channels
self.n = n_channels
def update(self, angles_deg):
smoothed = []
for i, ang in enumerate(angles_deg):
ang_rad = np.deg2rad(ang)
c, s = np.cos(ang_rad), np.sin(ang_rad)
if self.cos_state[i] is None:
self.cos_state[i] = c
self.sin_state[i] = s
else:
self.cos_state[i] = self.alpha * c + (1 - self.alpha) * self.cos_state[i]
self.sin_state[i] = self.alpha * s + (1 - self.alpha) * self.sin_state[i]
smoothed_ang = np.rad2deg(np.arctan2(self.sin_state[i], self.cos_state[i]))
smoothed.append(smoothed_ang)
return smoothed

Binary file not shown.

File diff suppressed because one or more lines are too long

36
mac.py Normal file
View File

@ -0,0 +1,36 @@
import cv2
import mediapipe as mp
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_pose = mp.solutions.pose
cap = cv2.VideoCapture(0)
with mp_pose.Pose(
min_detection_confidence=0.5,
min_tracking_confidence=0.5) as pose:
while cap.isOpened():
success, image = cap.read()
if not success:
print("Ignoring empty camera frame.")
continue
# To improve performance, optionally mark the image as not writeable to
# pass by reference.
image.flags.writeable = False
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
results = pose.process(image)
# Draw the pose annotation on the image.
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
mp_drawing.draw_landmarks(
image,
results.pose_landmarks,
mp_pose.POSE_CONNECTIONS,
landmark_drawing_spec=mp_drawing_styles.get_default_pose_landmarks_style())
# Flip the image horizontally for a selfie-view display.
cv2.imshow('MediaPipe Pose', cv2.flip(image, 1))
if cv2.waitKey(5) & 0xFF == 27:
break
cap.release()

219
main.py Normal file
View File

@ -0,0 +1,219 @@
import json
import os
import pickle
import socket
import sys
import torch
from ultralytics import YOLO
import cv2
import time
import poses
import utils
from calculate import normalize_pose, compare_poses_boolean
from draw import draw_new
from utils import find_closest
from video_methods import initialize_method
model = YOLO("yolo11s-pose.pt")
model.to(torch.device('cuda:0'))
if len(sys.argv) == 2:
method_type = sys.argv[1]
else:
print("Podaj argument 'cam', albo 'net'.")
exit(1)
method = initialize_method(method_type)
do_pose_shot = False
def click_event(event, x, y, flags, param):
global do_pose_shot
if event == cv2.EVENT_LBUTTONDOWN: # lewy przycisk myszy
do_pose_shot = not do_pose_shot
def main():
last_time = time.time()
currTimeIndex = 0
currIndex = None
currMove = None
currStatus = "Zacznij tanczyc"
mehCount = 0
goodCount = 0
failCount = 0
failRate = 10
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("0.0.0.0", 13425))
server_socket.listen()
print("czekam na clienta...")
client_socket, _ = server_socket.accept()
print("mam clienta!")
data = client_socket.recv(1024).decode()
if not data.startswith("id_"):
client_socket.close()
server_socket.close()
return
map = data.replace("id_", "").replace("\n", "").strip()
if not os.path.isfile(f'moves_{map}.pkl'):
print(map)
print("moves_" + map + ".pkl")
client_socket.sendall("not_exists".encode())
client_socket.close()
server_socket.close()
return
moves = []
with open(f'moves_{map}.pkl', 'rb') as f: # 'rb' = read binary
moves = pickle.load(f)
startValue = moves[0][0]
totalCount = len(moves)
for i, move in enumerate(moves):
moves[i] = ((move[0] - startValue) / 1000, move[1], move[2])
currIndex = 1
currTimeIndex = time.time()
deltaTime = time.time()
currStatus = f"Zaczoles tanczyc {currIndex}"
currMove = moves[0]
doStreak = False
streak = 0
doing = 0
actuallyDoing = False
while True:
doing += 1
frame = method.receive_frame()
frame = cv2.flip(frame, 1)
results = model(frame, verbose=False)
if not actuallyDoing:
client_socket.sendall("start".encode())
actuallyDoing = True
current_time = time.time()
delta = current_time - last_time
last_time = current_time
if doing % 30 == 0:
if doStreak:
streak += 5
client_socket.sendall(f"streak_{streak}".encode())
else:
streak = 0
client_socket.sendall(f"streak_0".encode())
fps = 1 / delta if delta > 0 else float('inf')
# print(f"\rDelta: {delta:.4f}s, FPS: {fps:.2f}", end="")
if len(results) != 0:
result = results[0]
kpts = result.keypoints.data[0] if len(result.keypoints.data) else None
if kpts is None:
continue
img = frame
normalized = normalize_pose(result.keypoints.xy.cpu().numpy()[0])
draw = utils.normalize(result.keypoints.xy.cpu().numpy()[0])
cv2.imshow('you', draw_new(draw * 100 + 100))
if currTimeIndex != 0 and moves.index(find_closest(moves, time.time() - currTimeIndex)) == len(moves) - 1:
mehCount = abs(totalCount - (failCount + goodCount))
stats = {
"failCount": failCount,
"goodCount": goodCount,
"mehCount": mehCount,
"percentage": (goodCount + (0.85 * mehCount)) / totalCount * 100
}
client_socket.sendall(f"finish_{json.dumps(stats)}".encode())
print(
f"PODSUMOWANIE: FAIL {failCount} MEH: {mehCount} PERFECT: {goodCount} PERCENTAGE: {(goodCount + (0.85 * mehCount)) / totalCount * 100}%")
cv2.destroyAllWindows()
break
# thread = Thread(target=print_animation, args=(moves, False))
# thread.start()
else:
changed = False
closest = find_closest(moves, time.time() - currTimeIndex)
cv2.imshow('Dots', draw_new(utils.normalize(closest[2]) * 250 + 250))
if abs((time.time() - currTimeIndex) - moves[currIndex][0]) > failRate:
currStatus = f"FAIL!"
failCount += 1
doStreak = False
if compare_poses_boolean(closest[1], normalized):
# delays += (time.time() - deltaTime - moves[0][0]) * 1000
# delaysCount += 1
# currStatus = f"SUPER! {currIndex} Zostalo {len(moves)} Delay {(time.time() - currTimeIndex - closest[0]) / 1000}ms"
deltaTime = time.time()
currIndex = moves.index(closest) + 1
goodCount += 1
changed = True
doStreak = True
if not changed and compare_poses_boolean(moves[currIndex][1], normalized):
# delays += (time.time() - deltaTime - moves[0][0]) * 1000
# delaysCount += 1
# currStatus = f"SUPER! {currIndex} Zostalo {len(moves)} Delay {(time.time() - currTimeIndex - closest[0]) / 1000}ms"
deltaTime = time.time()
changed = True
currIndex += 1
goodCount += 1
doStreak = True
# if do_pose_shot:
# moves.append((time.time() - startTime, normalize_pose(result.keypoints.xy.cpu().numpy()[0]), result.keypoints.xy.cpu()[0]))
# elif len(moves) != 0:
# with open('moves.pkl', 'wb') as f: # 'wb' = write binary
# pickle.dump
# (moves, f)
#
# exit(1)
cv2.putText(
img, # obraz
currStatus, # tekst
(50, 100), # pozycja (x, y) lewego dolnego rogu tekstu
cv2.FONT_HERSHEY_SIMPLEX, # czcionka
1, # rozmiar (skalowanie)
(0, 0, 255), # kolor (BGR) - tutaj czerwony
2, # grubość linii
cv2.LINE_AA # typ antyaliasingu
)
cv2.imshow('Klatka z kamerki', img)
cv2.setMouseCallback('Klatka z kamerki', click_event)
cv2.waitKey(1) # Czekaj na naciśnięcie klawisza
try:
while True:
main()
except KeyboardInterrupt:
pass

BIN
moves.pkl Normal file

Binary file not shown.

43
moves_3d.py Normal file
View File

@ -0,0 +1,43 @@
import cv2
import mediapipe as mp
import cv2
import mediapipe as mp
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_pose = mp.solutions.pose
cap = cv2.VideoCapture(0)
with mp_pose.Pose(
min_detection_confidence=0.5,
min_tracking_confidence=0.5) as pose:
while cap.isOpened():
success, image = cap.read()
if not success:
print("Ignoring empty camera frame.")
# If loading a video, use 'break' instead of 'continue'.
continue
# To improve performance, optionally mark the image as not writeable to
# pass by reference.
image.flags.writeable = False
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
results = pose.process(image)
print(f"\r{results.pose_world_landmarks[0]}", end="")
# Draw the pose annotation on the image.
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
mp_drawing.draw_landmarks(
image,
results.pose_landmarks,
mp_pose.POSE_CONNECTIONS,
landmark_drawing_spec=mp_drawing_styles.get_default_pose_landmarks_style())
# Flip the image horizontally for a selfie-view display.
landmarks = results.pose_world_landmarks.landmark
print(landmark)
cap.release()

60
moves_3d_mp4.py Normal file
View File

@ -0,0 +1,60 @@
import pickle
import time
import cv2
from ultralytics import YOLO
from calculate import normalize_pose
from utils import normalize
# Wczytanie wideo
cap = cv2.VideoCapture("input.mp4")
fps = cap.get(cv2.CAP_PROP_FPS)
width = 1920
height = 1080
# Ustawienia zapisu wideo
fourcc = cv2.VideoWriter_fourcc(*"avc1")
out = cv2.VideoWriter("output.mp4", fourcc, fps, (width, height))
# Wczytanie modelu YOLOv8 Pose
model = YOLO("yolo11x-pose.pt", verbose=False) # Twój model pose
moves = []
started = False
frame_id = 0
while True:
ok, frame = cap.read()
if not ok:
break
# Skalowanie do 640x640
frame_resized = cv2.resize(frame, (width, height))
# Wykrywanie poz
results = model.predict(frame_resized, verbose=False)
# Rysowanie punktów 2D
for result in results:
if result.keypoints is not None and len(result.keypoints.xy) > 0:
for keypoint in result.keypoints.xy[0]: # keypoints[0] bo dla jednej osoby
if not started:
frame_id = 0
started = True
x, y = keypoint # współrzędne + confidence
x = int(x)
y = int(y)
cv2.circle(frame_resized, (x, y), 5, (0, 255, 0), -1) # zielone kropki
moves.append((frame_id * 1 / fps, normalize_pose(result.keypoints.xy.cpu().numpy()[0]), normalize(result.keypoints.xy.cpu()[0]) * 160 + 250))
out.write(frame_resized)
frame_id += 1
with open('moves2.pkl', 'wb') as f: # 'wb' = write binary
pickle.dump(moves, f)
cap.release()
out.release()
print("Zapisano: output.mp4")

62
moves_dump.py Normal file
View File

@ -0,0 +1,62 @@
import json
import pickle
import time
import cv2
import numpy as np
import utils
from draw import draw_new
# moves = {}
better_moves = {}
with open('replay_tpose.pkl', 'rb') as f: # 'rb' = read binary
moves = pickle.load(f)
movesCopy = {}
for move in moves:
# listx = moves[move].tolist()
# print(type(listx))
# if type(listx) != list:
# listx = listx.tolist()
movesCopy[move.replace(".jpg", "")] = moves[move].tolist()
with open("plikv10.json", "w", encoding="utf-8") as f:
json.dump(movesCopy, f)
exit(1)
startValue = moves[0][0]
totalCount = len(moves)
for i, move in enumerate(moves):
moves[i] = (move[0] - startValue, move[1], move[2])
# left_hip = move[2][11] # Left Hip
# right_hip = move[2][12] # Right Hip
# center = (left_hip + right_hip) / 2
#
# # Normalizacja względem środka ciała
# normalized_keypoints = move[2] - center
#
# better_moves[round((move[0] - startValue) * 1000)] = normalized_keypoints.tolist()
#
# # scale = utils.distance(move[2][11], move[2][12])
# # print(scale)
# draw = normalized_keypoints + 200
# Do rysowania (np. przesunięcie na ekran)
draw = utils.normalize(move[2])
better_moves[round((move[0] - startValue) * 1000)] = draw.tolist()
# cv2.imshow('you', draw_new(draw))
# cv2.waitKey(1)
# time.sleep(0.1)
with open("plik-234.json", "w", encoding="utf-8") as f:
json.dump(better_moves, f)

47
moves_dump_2.py Normal file
View File

@ -0,0 +1,47 @@
import json
import pickle
import time
import cv2
import numpy as np
import utils
from draw import draw_new
moves = []
better_moves = {}
with open('moves.pkl', 'rb') as f: # 'rb' = read binary
moves = pickle.load(f)
startValue = moves[0][0]
totalCount = len(moves)
for i, move in enumerate(moves):
moves[i] = (move[0] - startValue, move[1], move[2])
# left_hip = move[2][11] # Left Hip
# right_hip = move[2][12] # Right Hip
# center = (left_hip + right_hip) / 2
#
# # Normalizacja względem środka ciała
# normalized_keypoints = move[2] - center
#
# better_moves[round((move[0] - startValue) * 1000)] = normalized_keypoints.tolist()
#
# # scale = utils.distance(move[2][11], move[2][12])
# # print(scale)
# draw = normalized_keypoints + 200
# Do rysowania (np. przesunięcie na ekran)
draw = utils.normalize(move[2])
better_moves[round((move[0] - startValue) * 1000)] = draw.tolist()
# cv2.imshow('you', draw_new(draw))
# cv2.waitKey(1)
# time.sleep(0.1)
with open("plik.json", "w", encoding="utf-8") as f:
json.dump(better_moves, f)

116
moves_videopose3d.py Normal file
View File

@ -0,0 +1,116 @@
import cv2
import torch
import numpy as np
from common.model import TemporalModel
from common.camera import *
# from common.utils import evaluate
from ultralytics import YOLO
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # not strictly needed in newer matplotlib
import time
# --- 1. Inicjalizacja modelu 3D VideoPose3D ---
model_3d = TemporalModel(
num_joints_in=17,
in_features=2,
num_joints_out=17,
filter_widths=[3,3,3,3],
causal=False
)
chk = torch.load("checkpoint/pretrained_h36m_detectron_coco.bin", map_location='cpu')
model_3d.load_state_dict(chk, strict=False)
model_3d.eval()
# --- 2. Inicjalizacja modelu YOLO (pose keypoints) ---
yolo = YOLO('yolo11s-pose.pt') # używamy najmniejszej wersji dla szybkości
# --- 3. Wczytanie wideo ---
cap = cv2.VideoCapture("input.mp4")
frame_buffer = []
BUFFER_SIZE = 243 # VideoPose3D potrzebuje sekwencji
fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(111, projection='3d')
# inicjalizacja scatter i linii szkieletu
scatter = ax.scatter([], [], [], c='r')
skeleton = [ (0, 1), (1, 2), (2, 3), (0, 4), (4, 5), (5, 6), (0, 7), (7, 8), (8, 9), (7, 12), (12, 13), (13, 14), (7, 10), (10, 11), (11, 12) ]
skeleton_lines = []
for _ in skeleton:
line, = ax.plot([], [], [], c='b')
skeleton_lines.append(line)
ax.set_xlim3d(-1, 1)
ax.set_ylim3d(-1, 1)
ax.set_zlim3d(0, 2)
ax.view_init(elev=20, azim=-70)
plt.ion()
plt.show()
while True:
ret, frame = cap.read()
if not ret:
break
# --- 4. Detekcja keypointów z YOLO ---
results = yolo(frame)
if len(results) == 0 or len(results[0].keypoints.xy) == 0:
continue
# Zakładamy 1 osobę na klatkę (dla uproszczenia)
keypoints = results[0].keypoints.xy[0] # shape [17, 2]
keypoints = np.array(keypoints)
# Normalizacja do [0,1] (opcjonalnie zależnie od VideoPose3D)
keypoints[:, 0] /= frame.shape[1]
keypoints[:, 1] /= frame.shape[0]
frame_buffer.append(keypoints)
# --- 5. Jeśli mamy pełną sekwencję, predykcja 3D ---
skeleton = [
(0, 1), (1, 2), (2, 3), (0, 4), (4, 5), (5, 6),
(0, 7), (7, 8), (8, 9), (7, 12), (12, 13), (13, 14),
(7, 10), (10, 11), (11, 12)
]
# --- after getting pred_3d ---
if len(frame_buffer) == BUFFER_SIZE:
seq_2d = torch.tensor(np.array(frame_buffer)).unsqueeze(0).float()
with torch.no_grad():
pred_3d = model_3d(seq_2d)
pose_3d = pred_3d[0, -1].numpy() # [17,3]
# --- 2D overlay ---
# for i, kp in enumerate(frame_buffer[-1]):
# x, y = int(kp[0] * frame.shape[1]), int(kp[1] * frame.shape[0])
# cv2.circle(frame, (x, y), 5, (0, 255, 0), -1)
# cv2.imshow("2D Pose", frame)
# cv2.waitKey(1)
pose_3d = pose_3d[:, [0, 2, 1]] # X, Z, Y
pose_3d[:, 2] *= -1
# --- 3D update ---
xs, ys, zs = pose_3d[:, 0], pose_3d[:, 1], pose_3d[:, 2]
# update scatter
scatter._offsets3d = (xs, ys, zs)
# update skeleton lines
for idx, (a, b) in enumerate(skeleton):
skeleton_lines[idx].set_data([xs[a], xs[b]], [ys[a], ys[b]])
skeleton_lines[idx].set_3d_properties([zs[a], zs[b]])
plt.draw()
plt.pause(0.001)
print(pose_3d.tolist())
frame_buffer.pop(0)
cap.release()
cv2.destroyAllWindows()

26
ploting.py Normal file
View File

@ -0,0 +1,26 @@
import matplotlib.pyplot as plt
import queue
data_queue = queue.Queue()
x_data, y_data = [], []
fig, ax = plt.subplots()
line, = ax.plot([], [], 'r-')
def init():
ax.set_xlim(0, 100)
ax.set_ylim(0, 10)
return line,
def update(frame):
# sprawdzamy, czy są nowe dane w kolejce
while not data_queue.empty():
value = data_queue.get()
x_data.append(len(x_data))
y_data.append(value)
if len(x_data) > 100:
x_data.pop(0)
y_data.pop(0)
line.set_data(x_data, y_data)
return line,

1
poses.py Normal file
View File

@ -0,0 +1 @@
t_pose = [ 0.079178 , 0.1963 , 0.098774 , 0.033032 , 0.99646 , 0.08401 , 0.99999, 0.0049546, -0.99134 , 0.13132, -0.99791, -0.064541, 0.063086, 0.99801, -0.03562, 0.99936, -0.012939, 0.99992, 0.02004, 0.9998]

48
receive_images.py Normal file
View File

@ -0,0 +1,48 @@
import socket
import cv2
import numpy as np
import struct
HOST = "0.0.0.0" # nasłuchuj na wszystkich interfejsach
PORT = 9999
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen(1)
print("Serwer nasłuchuje na port", PORT)
conn, addr = server_socket.accept()
print("Połączono z:", addr)
data = b""
payload_size = struct.calcsize("Q") # 8 bajtów na długość ramki
while True:
while len(data) < payload_size:
packet = conn.recv(4096)
if not packet:
break
data += packet
if not data:
break
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack("Q", packed_msg_size)[0]
while len(data) < msg_size:
data += conn.recv(4096)
frame_data = data[:msg_size]
data = data[msg_size:]
frame = np.frombuffer(frame_data, dtype=np.uint8)
frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
cv2.imshow("Odebrany obraz", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
conn.close()
server_socket.close()
cv2.destroyAllWindows()

62
receiver.py Normal file
View File

@ -0,0 +1,62 @@
import socket
import struct
import numpy as np
import cv2
import time
HOST = '0.0.0.0'
PORT = 9999
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, PORT))
sock.listen(1)
conn, addr = sock.accept()
print(f"Connected by {addr}")
total_bytes_received = 0
start_time = time.time()
def recvall(sock, n):
data = b''
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data += packet
return data
try:
while True:
# Odbiór długości
packed_len = recvall(conn, 4)
if not packed_len:
break
length = struct.unpack('!I', packed_len)[0]
# Odbiór danych
data = recvall(conn, length)
if not data:
break
total_bytes_received += length
# Dekodowanie JPEG
img_array = np.frombuffer(data, dtype=np.uint8)
frame = cv2.imdecode(img_array, cv2.IMREAD_COLOR)
cv2.imshow("Stream", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
elapsed = time.time() - start_time
if elapsed >= 1.0:
print(f"Download speed: {total_bytes_received * 8 / 1e6:.2f} Mbps")
total_bytes_received = 0
start_time = time.time()
finally:
conn.close()
sock.close()
cv2.destroyAllWindows()

68
record.py Normal file
View File

@ -0,0 +1,68 @@
import pickle
import sys
import torch
from ultralytics import YOLO
import cv2
import time
import utils
from calculate import normalize_pose, compare_poses_boolean
from draw import draw_new
from utils import find_closest
from video_methods import initialize_method
model = YOLO("yolo11x-pose.pt")
model.to(torch.device('cuda:0'))
if len(sys.argv) == 2:
method_type = sys.argv[1]
else:
print("Podaj argument 'cam', albo 'net'.")
exit(1)
method = initialize_method(method_type)
do_pose_shot = False
startTime = 0
def click_event(event, x, y, flags, param):
global do_pose_shot, startTime
if event == cv2.EVENT_LBUTTONDOWN: # lewy przycisk myszy
do_pose_shot = not do_pose_shot
if do_pose_shot:
startTime = time.time()
def main():
moves = []
while True:
frame = method.receive_frame()
frame = cv2.flip(frame, 1)
results = model(frame, verbose=False)
if len(results) != 0:
result = results[0]
kpts = result.keypoints.data[0] if len(result.keypoints.data) else None
if kpts is None:
continue
img = frame
if do_pose_shot:
moves.append((time.time() - startTime, normalize_pose(result.keypoints.xy.cpu().numpy()[0]), result.keypoints.xy.cpu()[0]))
elif len(moves) != 0:
with open('moves.pkl', 'wb') as f: # 'wb' = write binary
pickle.dump(moves, f)
exit(1)
cv2.imshow('Klatka z kamerki', img)
cv2.setMouseCallback('Klatka z kamerki', click_event)
cv2.waitKey(1) # Czekaj na naciśnięcie klawisza
main()

58
record_one_pose.py Normal file
View File

@ -0,0 +1,58 @@
import pickle
import sys
import torch
from ultralytics import YOLO
import cv2
import time
import utils
from calculate import normalize_pose, compare_poses_boolean
from draw import draw_new
from utils import find_closest
from video_methods import initialize_method
model = YOLO("yolo11x-pose.pt")
model.to(torch.device('cuda:0'))
method = initialize_method("cam")
do_pose_shot = False
startTime = 0
def click_event(event, x, y, flags, param):
global do_pose_shot, startTime
if event == cv2.EVENT_LBUTTONDOWN: # lewy przycisk myszy
do_pose_shot = not do_pose_shot
if do_pose_shot:
startTime = time.time()
def main():
moves = []
while True:
frame = method.receive_frame()
frame = cv2.flip(frame, 1)
results = model(frame, verbose=False)
if len(results) != 0:
result = results[0]
kpts = result.keypoints.data[0] if len(result.keypoints.data) else None
if kpts is None:
continue
img = frame
if do_pose_shot:
print(normalize_pose(result.keypoints.xy.cpu().numpy()[0]))
exit(0)
cv2.imshow('Klatka z kamerki', img)
cv2.setMouseCallback('Klatka z kamerki', click_event)
cv2.waitKey(1) # Czekaj na naciśnięcie klawisza
main()

40
record_video_pose.py Normal file
View File

@ -0,0 +1,40 @@
import glob
import pickle
from tqdm import tqdm
import torch
from ultralytics import YOLO
import cv2
import time
import utils
from calculate import normalize_pose, compare_poses_boolean
from draw import draw_new
from utils import find_closest
from video_methods import initialize_method
model = YOLO("yolo11x-pose.pt")
model.to(torch.device('cuda:0'))
startTime = 0
def main():
moves = []
for i in tqdm(sorted(glob.glob("video/camA/*.jpg"), key=lambda f: int(__import__("re").search(r"\d+", f).group()))):
data = i.replace(f'video/camA\\', "")
frame = cv2.imread(f"video/camA/{data}")
results = model(frame, verbose=False)
if len(results) != 0:
result = results[0]
kpts = result.keypoints.data[0] if len(result.keypoints.data) else None
if kpts is None:
continue
moves.append((int(data.replace(".jpg", "")), normalize_pose(result.keypoints.xy.cpu().numpy()[0]), result.keypoints.xy.cpu()[0]))
with open('moves_makarena_best.pkl', 'wb') as f: # 'wb' = write binary
pickle.dump(moves, f)
main()

19
rotate.py Normal file
View File

@ -0,0 +1,19 @@
import cv2
import os
folder = r"video/camC" # ← podaj swoją ścieżkę
# rozszerzenia jakie chcesz obracać
ext = (".jpg", ".jpeg", ".png")
for filename in os.listdir(folder):
if filename.lower().endswith(ext):
path = os.path.join(folder, filename)
img = cv2.imread(path)
rotated = cv2.rotate(img, cv2.ROTATE_180)
cv2.imwrite(path, rotated) # nadpisanie pliku
print(f"Obrócono: {filename}")
print("Gotowe ✔️")

Binary file not shown.

Binary file not shown.

51
sender.py Normal file
View File

@ -0,0 +1,51 @@
import cv2
import socket
import zstandard as zstd
import struct
import time
from utils import resize_with_padding
SERVER_IP = '127.0.0.1'
SERVER_PORT = 9999
# Socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((SERVER_IP, SERVER_PORT))
# Kompresor Zstd
compressor = zstd.ZstdCompressor(level=10)
cap = cv2.VideoCapture(0) # kamerka
total_bytes_sent = 0
start_time = time.time()
JPEG_QUALITY = 25 # 0-100, im mniejsza, tym większa kompresja
try:
while True:
ret, frame = cap.read()
if not ret:
break
frame = resize_with_padding(frame)
# Konwersja do JPEG
_, buffer = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, JPEG_QUALITY])
data = buffer.tobytes()
# Wysyłanie długości + danych
sock.sendall(struct.pack('!I', len(data)))
sock.sendall(data)
total_bytes_sent += len(data)
elapsed = time.time() - start_time
if elapsed >= 1.0:
print(f"Upload speed: {total_bytes_sent * 8 / 1e6:.2f} Mbps") # w megabitach
total_bytes_sent = 0
start_time = time.time()
finally:
cap.release()
sock.close()

400
test.py

File diff suppressed because one or more lines are too long

64
utils.py Normal file
View File

@ -0,0 +1,64 @@
import math
import cv2
import numpy as np
def recvall(sock, n):
data = b''
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data += packet
return data
def distance(p1, p2):
return math.sqrt((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2)
import numpy as np
def normalize(move):
left_hip = move[11] # Left Hip
right_hip = move[12] # Right Hip
nose = move[0] # Nose (głowa)
# Środek bioder
center = (left_hip + right_hip) / 2
# Przesunięcie względem środka
normalized_keypoints = move - center
# Zamiast max_dist używamy stałej miary "rozmiaru ciała"
body_height = np.linalg.norm(nose[:2] - center[:2]) # np. odległość biodra-głowa
if body_height > 0:
normalized_keypoints[:, :2] /= body_height
draw = normalized_keypoints[:, :2]
return draw
def find_closest(moves, target):
return min(moves, key=lambda t: abs(t[0] - target))
def resize_with_padding(image, target_size=(640, 640)):
h, w = image.shape[:2]
target_w, target_h = target_size
# Oblicz współczynnik skalowania, zachowując proporcje
scale = min(target_w / w, target_h / h)
new_w, new_h = int(w * scale), int(h * scale)
# Resize obrazu
resized_image = cv2.resize(image, (new_w, new_h), interpolation=cv2.INTER_AREA)
# Stwórz tło (czarne) o wymiarach docelowych
output_image = np.zeros((target_h, target_w, 3), dtype=np.uint8)
# Oblicz offsety do wyśrodkowania obrazu
x_offset = (target_w - new_w) // 2
y_offset = (target_h - new_h) // 2
# Wklej resized image na tło
output_image[y_offset:y_offset+new_h, x_offset:x_offset+new_w] = resized_image
return output_image

65
video_methods.py Normal file
View File

@ -0,0 +1,65 @@
import socket
import struct
import time
import cv2
import numpy as np
from utils import recvall
methods = ["cam", "net"]
HOST = '0.0.0.0'
PORT = 9999
class Method:
def __init__(self, method_type):
self.method_type = method_type
if method_type == "cam":
self.cap = cv2.VideoCapture(0)
if not self.cap.isOpened():
print("Nie można otworzyć kamerki")
exit(1)
else:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.bind((HOST, PORT))
self.sock.listen(1)
print(f"Oczekuje podłączenia na: {HOST}:{PORT}")
self.conn, addr = self.sock.accept()
print(f"Podłączono przez {addr}")
self.total_bytes_received = 0
self.start_time = time.time()
def receive_frame(self):
if self.method_type == "cam":
_, frame = self.cap.read()
if not _:
exit(1)
else:
packed_len = recvall(self.conn, 4)
if not packed_len:
exit(1)
length = struct.unpack('!I', packed_len)[0]
data = recvall(self.conn, length)
if not data:
exit(1)
self.total_bytes_received += length
img_array = np.frombuffer(data, dtype=np.uint8)
frame = cv2.imdecode(img_array, cv2.IMREAD_COLOR)
return frame
def initialize_method(method_type):
if not method_type in methods:
return None
return Method(method_type)