diff --git a/boom.ipynb b/boom.ipynb index b1e140a..99bf65a 100644 --- a/boom.ipynb +++ b/boom.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 142, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -118,7 +118,7 @@ }, { "cell_type": "code", - "execution_count": 143, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -155,7 +155,7 @@ }, { "cell_type": "code", - "execution_count": 144, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -284,7 +284,7 @@ }, { "cell_type": "code", - "execution_count": 145, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -314,7 +314,7 @@ }, { "cell_type": "code", - "execution_count": 146, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -331,10 +331,10 @@ "mode": "markers+lines+text", "name": "16", "text": [ - "0", - "1", - "2", - "3" + "16:0", + "16:1", + "16:2", + "16:3" ], "textposition": "middle center", "type": "scatter3d", @@ -364,10 +364,10 @@ "mode": "markers+lines+text", "name": "17", "text": [ - "0", - "1", - "2", - "3" + "17:0", + "17:1", + "17:2", + "17:3" ], "textposition": "middle center", "type": "scatter3d", @@ -397,10 +397,10 @@ "mode": "markers+lines+text", "name": "18", "text": [ - "0", - "1", - "2", - "3" + "18:0", + "18:1", + "18:2", + "18:3" ], "textposition": "middle center", "type": "scatter3d", @@ -430,10 +430,10 @@ "mode": "markers+lines+text", "name": "19", "text": [ - "0", - "1", - "2", - "3" + "19:0", + "19:1", + "19:2", + "19:3" ], "textposition": "middle center", "type": "scatter3d", @@ -483,10 +483,10 @@ "mode": "markers+lines+text", "name": "20", "text": [ - "0", - "1", - "2", - "3" + "20:0", + "20:1", + "20:2", + "20:3" ], "textposition": "middle center", "type": "scatter3d", @@ -516,10 +516,10 @@ "mode": "markers+lines+text", "name": "21", "text": [ - "0", - "1", - "2", - "3" + "21:0", + "21:1", + "21:2", + "21:3" ], "textposition": "middle center", "type": "scatter3d", @@ -549,10 +549,10 @@ "mode": "markers+lines+text", "name": "22", "text": [ - "0", - "1", - "2", - "3" + "22:0", + "22:1", + "22:2", + "22:3" ], "textposition": "middle center", "type": "scatter3d", @@ -582,10 +582,10 @@ "mode": "markers+lines+text", "name": "23", "text": [ - "0", - "1", - "2", - "3" + "23:0", + "23:1", + "23:2", + "23:3" ], "textposition": "middle center", "type": "scatter3d", @@ -635,10 +635,10 @@ "mode": "markers+lines+text", "name": "24", "text": [ - "0", - "1", - "2", - "3" + "24:0", + "24:1", + "24:2", + "24:3" ], "type": "scatter3d", "x": [ @@ -667,10 +667,10 @@ "mode": "markers+lines+text", "name": "25", "text": [ - "0", - "1", - "2", - "3" + "25:0", + "25:1", + "25:2", + "25:3" ], "type": "scatter3d", "x": [ @@ -699,10 +699,10 @@ "mode": "markers+lines+text", "name": "26", "text": [ - "0", - "1", - "2", - "3" + "26:0", + "26:1", + "26:2", + "26:3" ], "type": "scatter3d", "x": [ @@ -731,10 +731,10 @@ "mode": "markers+lines+text", "name": "27", "text": [ - "0", - "1", - "2", - "3" + "27:0", + "27:1", + "27:2", + "27:3" ], "type": "scatter3d", "x": [ @@ -1625,15 +1625,15 @@ ], "source": [ "fig = go.Figure()\n", - "t_corners = plane_a.transformed_corners\n", - "for i, corners in enumerate(t_corners):\n", + "t_corners_a = plane_a.transformed_corners\n", + "for i, corners in enumerate(t_corners_a):\n", " fig.add_trace(\n", " go.Scatter3d(\n", " x=corners[:, 0],\n", " y=corners[:, 1],\n", " z=corners[:, 2],\n", " mode=\"markers+lines+text\",\n", - " text=list(range(4)),\n", + " text=list(map(lambda x: f\"{plane_a.ids[i]}:{x}\", range(4))),\n", " textposition=\"middle center\",\n", " name=str(plane_a.ids[i]),\n", " marker=dict(size=1),\n", @@ -1660,7 +1660,7 @@ " y=corners[:, 1],\n", " z=corners[:, 2],\n", " mode=\"markers+lines+text\",\n", - " text=list(range(4)),\n", + " text=list(map(lambda x: f\"{plane_b.ids[i]}:{x}\", range(4))),\n", " textposition=\"middle center\",\n", " name=str(plane_b.ids[i]),\n", " marker=dict(size=1),\n", @@ -1685,7 +1685,7 @@ " y=corners[:, 1],\n", " z=corners[:, 2],\n", " mode=\"markers+lines+text\",\n", - " text=list(range(4)),\n", + " text=list(map(lambda x: f\"{plane_c.ids[i]}:{x}\", range(4))),\n", " name=str(plane_c.ids[i]),\n", " marker=dict(size=1),\n", " )\n", @@ -1719,6 +1719,59 @@ ")\n", "fig.show()" ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[{name: 'a', ids: [16, 17, 18, 19], corners: [[...], ...]},\n",
+       " {name: 'b', ids: [20, 21, 22, 23], corners: [[...], ...]},\n",
+       " {name: 'c', ids: [24, 25, 26, 27], corners: [[...], ...]}]\n",
+       "-----------------------------------------------------------\n",
+       "type: 3 * {\n",
+       "    name: string,\n",
+       "    ids: var * int64,\n",
+       "    corners: var * var * var * float64\n",
+       "}
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import awkward as ak\n", + "from awkward import Record as AwkwardRecord, Array as AwkwardArray\n", + "\n", + "coords = AwkwardArray(\n", + " [\n", + " {\n", + " \"name\": \"a\",\n", + " \"ids\": plane_a.ids,\n", + " \"corners\": t_corners_a,\n", + " },\n", + " {\n", + " \"name\": \"b\",\n", + " \"ids\": plane_b.ids,\n", + " \"corners\": t_corners_b,\n", + " },\n", + " {\n", + " \"name\": \"c\",\n", + " \"ids\": plane_c.ids,\n", + " \"corners\": t_corners_c,\n", + " },\n", + " ]\n", + ")\n", + "display(coords)\n", + "_ = ak.to_parquet(coords, \"output/object_points.parquet\")" + ] } ], "metadata": { diff --git a/find_cute_object.py b/find_cute_object.py new file mode 100644 index 0000000..c822f47 --- /dev/null +++ b/find_cute_object.py @@ -0,0 +1,63 @@ +import cv2 +from cv2 import aruco +from datetime import datetime +from loguru import logger +from pathlib import Path +from typing import cast, Final +import awkward as ak +from cv2.typing import MatLike +import numpy as np + +NDArray = np.ndarray +CALIBRATION_PARQUET = Path("output") / "usbcam_cal.parquet" +OBJECT_POINTS_PARQUET = Path("output") / "object_points.parquet" +DICTIONARY: Final[int] = aruco.DICT_4X4_50 +# 400mm +MARKER_LENGTH: Final[float] = 0.4 + + +def gen(): + API = cv2.CAP_AVFOUNDATION + cap = cv2.VideoCapture(0, API) + while True: + ret, frame = cap.read() + if not ret: + logger.warning("Failed to grab frame") + break + yield frame + + +def main(): + aruco_dict = aruco.getPredefinedDictionary(DICTIONARY) + cal = ak.from_parquet(CALIBRATION_PARQUET)[0] + camera_matrix = cast(MatLike, ak.to_numpy(cal["camera_matrix"])) + distortion_coefficients = cast(MatLike, ak.to_numpy(cal["distortion_coefficients"])) + ops = ak.from_parquet(OBJECT_POINTS_PARQUET) + board = aruco.CharucoBoard( + size=(3, 3), squareLength=0.127, markerLength=0.097, dictionary=aruco_dict + ) + detector = aruco.CharucoDetector(board) + + for frame in gen(): + grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + # pylint: disable-next=unpacking-non-sequence + diamond_corners, diamond_ids, markers, marker_ids = detector.detectDiamonds( + grey + ) + # `markers` is [N, 1, 4, 2] + # `ids` is [N, 1] + if diamond_ids is not None: + aruco.drawDetectedDiamonds(frame, diamond_corners, diamond_ids) + cv2.imshow("frame", frame) + if (k := cv2.waitKey(1)) == ord("q"): + logger.info("Exiting") + break + elif k == ord("s"): + now = datetime.now().strftime("%Y%m%d%H%M%S") + file_name = f"aruco_{now}.png" + logger.info("Saving to {}", file_name) + cv2.imwrite(file_name, frame) + + +if __name__ == "__main__": + main() diff --git a/output/object_points.parquet b/output/object_points.parquet new file mode 100644 index 0000000..b36fa12 --- /dev/null +++ b/output/object_points.parquet @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c724e688289d04f446c963246a94f37083170ac92f1010e2350dbe634098fa8 +size 4897