From a43c2b93dde2a283bb8496f5a80ad3a5b5627ac8 Mon Sep 17 00:00:00 2001 From: leoogrizek <35898289+leoogrizek@users.noreply.github.com> Date: Tue, 25 Jul 2023 11:46:12 +0200 Subject: [PATCH 1/7] Updated some deprecated stuff, fixed windows not closing --- gen2-pointcloud/rgbd-pointcloud/main.py | 16 +++++++++------- gen2-pointcloud/rgbd-pointcloud/requirements.txt | 9 ++++----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/gen2-pointcloud/rgbd-pointcloud/main.py b/gen2-pointcloud/rgbd-pointcloud/main.py index 525f38a7..194a5ce8 100644 --- a/gen2-pointcloud/rgbd-pointcloud/main.py +++ b/gen2-pointcloud/rgbd-pointcloud/main.py @@ -25,12 +25,12 @@ monoLeft = pipeline.create(dai.node.MonoCamera) monoLeft.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P) -monoLeft.setBoardSocket(dai.CameraBoardSocket.LEFT) +monoLeft.setBoardSocket(dai.CameraBoardSocket.CAM_B) #CAM_B = left camera monoRight = pipeline.create(dai.node.MonoCamera) monoRight.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P) -monoRight.setBoardSocket(dai.CameraBoardSocket.RIGHT) - +monoRight.setBoardSocket(dai.CameraBoardSocket.CAM_C) #CAM_C = right camera + stereo = pipeline.createStereoDepth() stereo.setDefaultProfilePreset(dai.node.StereoDepth.PresetMode.HIGH_DENSITY) stereo.initialConfig.setMedianFilter(median) @@ -75,7 +75,7 @@ camRgb.setIspScale(1, 3) camRgb.setColorOrder(dai.ColorCameraProperties.ColorOrder.RGB) camRgb.initialControl.setManualFocus(130) - stereo.setDepthAlign(dai.CameraBoardSocket.RGB) + stereo.setDepthAlign(dai.CameraBoardSocket.CAM_A) #CAM_A = center camera camRgb.isp.link(xout_colorize.input) else: stereo.rectifiedRight.link(xout_colorize.input) @@ -133,10 +133,10 @@ def add_msg(self, name, msg): calibData = device.readCalibration() if COLOR: w, h = camRgb.getIspSize() - intrinsics = calibData.getCameraIntrinsics(dai.CameraBoardSocket.RGB, dai.Size2f(w, h)) + intrinsics = calibData.getCameraIntrinsics(dai.CameraBoardSocket.CAM_A, dai.Size2f(w, h)) else: w, h = monoRight.getResolutionSize() - intrinsics = calibData.getCameraIntrinsics(dai.CameraBoardSocket.RIGHT, dai.Size2f(w, h)) + intrinsics = calibData.getCameraIntrinsics(dai.CameraBoardSocket.CAM_C, dai.Size2f(w, h)) pcl_converter = PointCloudVisualizer(intrinsics, w, h) serial_no = device.getMxId() @@ -173,4 +173,6 @@ def add_msg(self, name, msg): cv2.imwrite(f"{serial_no}_{timestamp}_rectified_right.png", rectified_right) o3d.io.write_point_cloud(f"{serial_no}_{timestamp}.pcd", pcl_converter.pcl, compressed=True) elif key == ord("q"): - break + pcl_converter.close_window() + cv2.destroyAllWindows() + break \ No newline at end of file diff --git a/gen2-pointcloud/rgbd-pointcloud/requirements.txt b/gen2-pointcloud/rgbd-pointcloud/requirements.txt index 847d2098..32f00876 100644 --- a/gen2-pointcloud/rgbd-pointcloud/requirements.txt +++ b/gen2-pointcloud/rgbd-pointcloud/requirements.txt @@ -1,5 +1,4 @@ -opencv-python -depthai==2.16.0.0 -numpy -open3d==0.10.0.0; platform_machine != "armv7l" and python_version < "3.9" -torch \ No newline at end of file +numpy==1.21.5 +open3d==0.14.1 +depthai==2.22.0.0 +opencv-python==4.7.0 From 197662132db14c8f6629e41a52f9200e16f09c8b Mon Sep 17 00:00:00 2001 From: leoogrizek <35898289+leoogrizek@users.noreply.github.com> Date: Wed, 27 Sep 2023 19:18:19 +0200 Subject: [PATCH 2/7] new experiment --- gen2-geometry-fitting/README.md | 31 + gen2-geometry-fitting/example.gif | Bin 0 -> 6831387 bytes gen2-geometry-fitting/geometry_fitting.ipynb | 1122 ++++++++++++++++ gen2-geometry-fitting/geometry_fitting.py | 1206 ++++++++++++++++++ gen2-geometry-fitting/json/yolov5.json | 108 ++ gen2-geometry-fitting/requirements.txt | 9 + 6 files changed, 2476 insertions(+) create mode 100644 gen2-geometry-fitting/README.md create mode 100644 gen2-geometry-fitting/example.gif create mode 100644 gen2-geometry-fitting/geometry_fitting.ipynb create mode 100644 gen2-geometry-fitting/geometry_fitting.py create mode 100644 gen2-geometry-fitting/json/yolov5.json create mode 100644 gen2-geometry-fitting/requirements.txt diff --git a/gen2-geometry-fitting/README.md b/gen2-geometry-fitting/README.md new file mode 100644 index 00000000..d9887ca6 --- /dev/null +++ b/gen2-geometry-fitting/README.md @@ -0,0 +1,31 @@ +# Gen2 Geometry Fitting + +This example demonstrates fitting of predefined geometric primitives onto point clouds of objects detected in RGBD images. The device captures depth and color information and runs YOLOv5 on the image data. Detected bounding boxes are used to fit geometry onto subsets of the full point cloud. Possible types of geometry are plane, cuboid, sphere and cylinder, the fitted geometry depends on the YOLO detection label. You can expect up to 5FPS, depending on the geometry. Cylinder fitting is in beta and will take up to 3 seconds. The example was tested on a OAK-D PRO device. + +## Installation + +1. Clone the repository: + ```bash + git clone https://github.com/luxonis/depthai-experiments + cd [example-directory] + ``` +2. It is recommended to run this example in a virtual environment + ```bash + conda create --name myenv + conda activate myenv + ``` +3. Install the required packages: + ```bash + pip install -r requirements.txt + ``` + +## Usage + +The example can be run with + +```bash +python geometry_fitting.py +``` +If you would prefer running this in Jupyter, simply run all cells in `geometry_fitting.ipynb`. + +By default this example does not print out the parameters of detected shapes. If you want this functionality change the variable `verbose` to `True`. \ No newline at end of file diff --git a/gen2-geometry-fitting/example.gif b/gen2-geometry-fitting/example.gif new file mode 100644 index 0000000000000000000000000000000000000000..d358e459061c9e86abcd73a346181a5aff778df6 GIT binary patch literal 6831387 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