{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### Các tệp đã cho\n\n- **train_data.zip** và **test_data.zip** - chứa các tệp JSON có nhiều bảng. Điều quan trọng nhất là ```sample_data.json```, chứa các giá trị nhận dạng chính được sử dụng trong cuộc thi, cũng như các liên kết đến thông tin hình ảnh/lidar chính.\n    \n- **train_images.zip** và **test_images.zip** - chứa các tệp .jpeg tương ứng với các mẫu trong ```sample_data.json```\n- **train_lidar.zip** và **test_lidar.zip** - chứa các tệp .bin tương ứng với các mẫu trong ```sample_data.json```\n- **train_maps.zip** và **test_maps.zip** - chứa các bản đồ của toàn bộ khu vực mẫu.\n- **train.csv** - chứa tất cả ```sample_tokens``` trong nhóm tàu, cũng như các chú thích ở định dạng bắt buộc cho tất cả các đối tượng của nhóm tàu.\n- **sample_submission.csv** - chứa tất cả ```sample_tokens``` trong bộ thử nghiệm, với các dự đoán trống.","metadata":{}},{"cell_type":"markdown","source":"# CÁC BƯỚC THỰC HIỆN MÔ HÌNH\n1/Cài đặt các thư viện và module cần thiết.\n\n2/Tải dữ liệu và khởi tạo đối tượng LyftDataset từ SDK.\n\n3/Lấy thông tin về một số đối tượng trong tập dữ liệu như danh sách các category, thông tin về một sample annotation, scene, attribute, instance, v.v.\n\n4/Hiển thị và trực quan hóa dữ liệu bằng các hình ảnh và biểu đồ, bao gồm:\n\n    _Hiển thị hình ảnh từ một camera cụ thể.\n    \n    _Hiển thị dữ liệu LiDAR.\n    \n    _Vẽ biểu đồ 3D của dữ liệu LiDAR.\n    \n    _Hiển thị các hình ảnh tương ứng với các khung hình trong một scene.\n    \n    _Tạo và hiển thị GIF từ các khung hình trong một scene.\n    ","metadata":{}},{"cell_type":"markdown","source":"# **sử dụng mô hình lyft_dataset_sdk và thực hiện một số thao tác trên dữ liệu LiDAR trong tập dữ liệu của LyfT**\nĐÔI NÉT VỀ DỮ LIỆU LIDAR\n\nTrong tập dữ liệu của Lyft, dữ liệu LiDAR (Light Detection and Ranging) được sử dụng để thu thập thông tin về môi trường xung quanh phương tiện di chuyển. Dữ liệu LiDAR cung cấp một hình ảnh 3D về vật thể và cấu trúc xung quanh phương tiện.\n\nDữ liệu LiDAR được lưu trữ dưới dạng điểm (point cloud), trong đó mỗi điểm đại diện cho một vật thể hoặc một điểm trên bề mặt vật thể. Mỗi điểm trong point cloud được biểu diễn bằng tọa độ 3D (x, y, z) trong hệ tọa độ địa lý (GPS) và có thể có thêm các thuộc tính khác như mức độ phản xạ của điểm (intensity).\n\nTrong tập dữ liệu Lyft, dữ liệu LiDAR được gắn kết với các mẫu dữ liệu (sample data) và được lưu trữ dưới dạng các tệp tin LASER hoặc BIN. Mỗi mẫu dữ liệu có thể có nhiều khung hình (sweeps) LiDAR, mỗi khung hình bao gồm một loạt điểm LiDAR thu thập trong một khoảng thời gian ngắn.\n\nThông qua các phương pháp xử lý dữ liệu, ta có thể chuyển đổi dữ liệu LiDAR từ hệ tọa độ của LiDAR thành hệ tọa độ của phương tiện. Việc chuyển đổi này giúp định vị các điểm LiDAR trong không gian 3D liên quan đến phương tiện di chuyển.\n\nDữ liệu LiDAR trong tập dữ liệu Lyft rất hữu ích để phân tích môi trường xung quanh phương tiện và nhận diện các vật thể như xe, người đi bộ, đường, v.v. Các thuật toán xử lý dữ liệu LiDAR có thể được áp dụng để phân đoạn (segmentation) dữ liệu, nhận diện vật thể và xây dựng mô hình 3D của môi trường giao thông.","metadata":{}},{"cell_type":"markdown","source":"Cài đặt gói Python \"moviepy\" từ kho lưu trữ Git ","metadata":{}},{"cell_type":"markdown","source":"> > > > > > > > > > > # **** 1/ Cài đặt các thư viện và module cần thiết.","metadata":{}},{"cell_type":"code","source":"!pip install -U git+https://github.com/lyft/nuscenes-devkit moviepy >> /dev/tmp","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-06-05T14:33:24.618654Z","iopub.execute_input":"2023-06-05T14:33:24.619020Z","iopub.status.idle":"2023-06-05T14:34:15.065129Z","shell.execute_reply.started":"2023-06-05T14:33:24.618965Z","shell.execute_reply":"2023-06-05T14:34:15.063729Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"import module \"warnings\" để xử lý cảnh báo trong Python. Module này cho phép chúng ta quản lý và kiểm soát các cảnh báo được sinh ra bởi các thư viện và code ","metadata":{}},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\", category=DeprecationWarning)\nwarnings.filterwarnings(\"ignore\", category=UserWarning)\nwarnings.filterwarnings(\"ignore\", category=FutureWarning)\nfrom IPython.display import HTML","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:36:19.039218Z","iopub.execute_input":"2023-06-05T14:36:19.039600Z","iopub.status.idle":"2023-06-05T14:36:19.047180Z","shell.execute_reply.started":"2023-06-05T14:36:19.039543Z","shell.execute_reply":"2023-06-05T14:36:19.045727Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pdb\nimport cv2\nimport pandas as pd\nimport numpy as np\nfrom PIL import Image\nfrom pathlib import Path\nfrom matplotlib import pyplot as plt\nfrom mpl_toolkits.mplot3d import axes3d, Axes3D\n\n# Load the SDK\nfrom lyft_dataset_sdk.lyftdataset import LyftDataset, LyftDatasetExplorer, Quaternion, view_points\nfrom lyft_dataset_sdk.utils.data_classes import LidarPointCloud\n\nfrom moviepy.editor import ImageSequenceClip\nfrom tqdm import tqdm_notebook as tqdm\n\n%matplotlib inline","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","execution":{"iopub.status.busy":"2023-06-05T14:37:00.595548Z","iopub.execute_input":"2023-06-05T14:37:00.595926Z","iopub.status.idle":"2023-06-05T14:37:05.005827Z","shell.execute_reply.started":"2023-06-05T14:37:00.595871Z","shell.execute_reply":"2023-06-05T14:37:05.004760Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Giới thiệu về cấu trúc dữ liệu\nHãy cùng đi qua một giới thiệu từ trên xuống về cơ sở dữ liệu. Tập dữ liệu bao gồm các khối xây dựng cơ bản sau đây:\n\n\n* scene - Đoạn video dài 25-45 giây về hành trình của một chiếc ô tô.\n* sample - Một hình ảnh được chú thích của một scene tại một thời điểm cụ thể.\n* sample_data - Dữ liệu được thu thập từ một cảm biến cụ thể.\n* sample_annotation - Một phiên bản được chú thích của một đối tượng trong tầm quan tâm của chúng ta.\n* instance - Liệt kê tất cả các phiên bản đối tượng mà chúng ta đã quan sát được.\n* category - Phân loại các loại đối tượng (ví dụ: phương tiện, con người).\n* attribute - Thuộc tính của một phiên bản có thể thay đổi trong khi loại vẫn giữ nguyên.\n* visibility - (hiện không được sử dụng)\n* sensor - Một loại cảm biến cụ thể.\n* calibrated sensor - Định nghĩa của một cảm biến cụ thể đã được hiệu chuẩn trên một phương tiện cụ thể.\n* ego_pose - Vị trí của xe chủ động vào một thời điểm cụ thể.\n* log - Thông tin nhật ký từ đó dữ liệu được trích xuất.\n* map - Dữ liệu bản đồ được lưu trữ dưới dạng mặt nạ ngữ nghĩa nhị phân từ góc nhìn từ trên xuống.","metadata":{}},{"cell_type":"markdown","source":"Dữ liệu có dạng nhiều bảng và định dạng lồng vào nhau. Tất cả các tệp JSON đều chứa các bảng đơn có mã thông báo xác định có thể được sử dụng để nối với các tệp/bảng khác. Tất cả các hình ảnh và tệp lidar đều tương ứng với một mẫu trong sample_data.json\n\nChúng tôi sẽ sử dụng SDK Bộ dữ liệu của lyft để thực hiện phân tích dữ liệu\n\n[lyft's Dataset SDK](https://github.com/lyft/nuscenes-devkit/) ","metadata":{}},{"cell_type":"markdown","source":"Các liên kết tượng trưng này được tạo để đảm bảo rằng các thư mục images, maps, lidar, và data có sẵn trong thư mục làm việc hiện tại, và chúng có thể trỏ đến các thư mục nguồn chứa dữ liệu từ /kaggle/input/3d-object-detection-for-autonomous-vehicles. Điều này giúp SDK LyftDataset có thể tìm kiếm và truy cập dữ liệu cần thiết từ các thư mục này một cách thuận tiện.","metadata":{}},{"cell_type":"markdown","source":"> > > > > > > > > # **** 2/ Tải dữ liệu và khởi tạo đối tượng LyftDataset từ SDK.","metadata":{}},{"cell_type":"code","source":"# LyftDataset SDK, nó yêu cầu các thư mục được đặt tên là `images`, `maps`, `lidar`\n\n!ln -s /kaggle/input/3d-object-detection-for-autonomous-vehicles/train_images images\n!ln -s /kaggle/input/3d-object-detection-for-autonomous-vehicles/train_maps maps\n!ln -s /kaggle/input/3d-object-detection-for-autonomous-vehicles/train_lidar lidar\n!ln -s /kaggle/input/3d-object-detection-for-autonomous-vehicles/train_data data","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:38:23.568903Z","iopub.execute_input":"2023-06-05T14:38:23.569365Z","iopub.status.idle":"2023-06-05T14:38:27.972546Z","shell.execute_reply.started":"2023-06-05T14:38:23.569308Z","shell.execute_reply":"2023-06-05T14:38:27.971278Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* Cụ thể, các đối số được truyền vào:\n* \n* data_path='.': Đây là đường dẫn tới thư mục chứa dữ liệu Lyft. Trong trường hợp này, '.' đại diện cho thư mục hiện tại, nghĩa là thư mục trong đó đoạn mã này đang được thực thi.\n* json_path='data/': Đây là đường dẫn tới thư mục chứa các tệp JSON của dữ liệu Lyft. Thư mục này được liên kết tới trong dòng mã trước đó bằng lệnh !ln -s /kaggle/input/3d-object-detection-for-autonomous-vehicles/train_data data.\n* verbose=True: Đối số này xác định rằng bạn muốn hiển thị thông tin chi tiết khi tạo đối tượng LyftDataset.\n* Sau khi đối tượng LyftDataset được khởi tạo, bạn có thể sử dụng nó để truy cập và làm việc với các bảng dữ liệu và chức năng trong SDK của Lyft, như category, sample_annotation, scene, vv.","metadata":{}},{"cell_type":"code","source":"lyftdata = LyftDataset(data_path='.', json_path='data/', verbose=True)","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:38:33.705418Z","iopub.execute_input":"2023-06-05T14:38:33.705855Z","iopub.status.idle":"2023-06-05T14:39:02.377117Z","shell.execute_reply.started":"2023-06-05T14:38:33.705780Z","shell.execute_reply":"2023-06-05T14:39:02.375974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Thông tin về số lượng bản ghi trong các bảng dữ liệu Lyft được tải và các thời gian tải dữ liệu.\n* 9 category: Số lượng danh mục (loại đối tượng) có sẵn trong dữ liệu Lyft.\n* 18 attribute: Số lượng thuộc tính (đặc điểm) có sẵn trong dữ liệu Lyft.\n* 4 visibility: Số lượng trạng thái hiển thị (có thể nhìn thấy hoặc không nhìn thấy) có sẵn trong dữ liệu Lyft.\n* 18421 instance: Số lượng trường hợp (ví dụ: xe cụ thể) có sẵn trong dữ liệu Lyft.\n* 10 sensor: Số lượng cảm biến có sẵn trong dữ liệu Lyft.\n* 148 calibrated_sensor: Số lượng cảm biến được hiệu chuẩn có sẵn trong dữ liệu Lyft.\n* 177789 ego_pose: Số lượng vị trí ego (vị trí của xe tự hành) có sẵn trong dữ liệu Lyft.\n* 180 log: Số lượng nhật ký (dữ liệu ghi lại) có sẵn trong dữ liệu Lyft.\n* 180 scene: Số lượng cảnh (giao lộ hoặc đoạn đường cụ thể) có sẵn trong dữ liệu Lyft.\n* 22680 sample: Số lượng mẫu (khung hình cụ thể) có sẵn trong dữ liệu Lyft.\n* 189504 sample_data: Số lượng dữ liệu mẫu (hình ảnh, lidar, radar, vv.) có sẵn trong dữ liệu Lyft.\n* 638179 sample_annotation: Số lượng chú thích mẫu (chú thích vị trí, hình dạng, vv.) có sẵn trong dữ liệu Lyft.\n* 1 map: Số lượng bản đồ có sẵn trong dữ liệu Lyft.","metadata":{}},{"cell_type":"markdown","source":"LyftDataset chứa một số bảng. Mỗi bảng là một danh sách các bản ghi và mỗi bản ghi là một từ điển. Ví dụ: bản ghi đầu tiên của bảng danh mục được lưu trữ tại:","metadata":{}},{"cell_type":"markdown","source":"lyftdata.category[0]: Đây là ví dụ về cách truy cập vào bản ghi đầu tiên trong bảng category. Mỗi bản ghi trong bảng này là một từ điển (dictionary) chứa các trường thông tin như name (tên) và description (mô tả) của danh mục. Bằng cách sử dụng chỉ số [0], chúng ta có thể truy cập vào bản ghi đầu tiên.","metadata":{}},{"cell_type":"code","source":"lyftdata.category[0]","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:40:02.792340Z","iopub.execute_input":"2023-06-05T14:40:02.792834Z","iopub.status.idle":"2023-06-05T14:40:02.802270Z","shell.execute_reply.started":"2023-06-05T14:40:02.792768Z","shell.execute_reply":"2023-06-05T14:40:02.801047Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"cat_token = lyftdata.category[0]['token']: Đoạn mã này trích xuất giá trị của trường token (mã định danh duy nhất) từ bản ghi đầu tiên trong bảng category và lưu trữ vào biến cat_token.","metadata":{}},{"cell_type":"code","source":"cat_token = lyftdata.category[0]['token']\ncat_token","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:40:05.618878Z","iopub.execute_input":"2023-06-05T14:40:05.619396Z","iopub.status.idle":"2023-06-05T14:40:05.624845Z","shell.execute_reply.started":"2023-06-05T14:40:05.619345Z","shell.execute_reply":"2023-06-05T14:40:05.624150Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"lyftdata.get('category', cat_token): Đoạn mã này sử dụng phương thức get của LyftDataset để lấy lại bản ghi từ bảng category thông qua token. Bằng cách truyền 'category' làm đối số đầu tiên và cat_token làm đối số thứ hai, chúng ta có thể truy xuất lại bản ghi ban đầu từ bảng category. Kết quả là bản ghi ban đầu và bản ghi được lấy lại là giống nhau.","metadata":{}},{"cell_type":"code","source":"lyftdata.get('category', cat_token)","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:40:08.687207Z","iopub.execute_input":"2023-06-05T14:40:08.687572Z","iopub.status.idle":"2023-06-05T14:40:08.694684Z","shell.execute_reply.started":"2023-06-05T14:40:08.687522Z","shell.execute_reply":"2023-06-05T14:40:08.693600Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":" khôi phục bản ghi tương tự!","metadata":{}},{"cell_type":"markdown","source":"lyftdata.sample_annotation[0]: Đây là ví dụ về cách truy cập vào bản ghi đầu tiên trong bảng sample_annotation. Bản ghi này chứa thông tin về chú thích của một mẫu (khung hình cụ thể) trong dữ liệu Lyft.","metadata":{}},{"cell_type":"code","source":"lyftdata.sample_annotation[0]","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:40:11.304108Z","iopub.execute_input":"2023-06-05T14:40:11.304636Z","iopub.status.idle":"2023-06-05T14:40:11.312255Z","shell.execute_reply.started":"2023-06-05T14:40:11.304545Z","shell.execute_reply":"2023-06-05T14:40:11.311214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Điều này cũng có trường `token` (tất cả đều có). Ngoài ra, nó có một số trường có định dạng [a-z]*\\_token, _e.g._ instance_token. Đây là các khóa ngoại trong thuật ngữ cơ sở dữ liệu, nghĩa là chúng trỏ đến một bảng khác.\nSử dụng `lyftdata.get()`, chúng ta có thể lấy bất kỳ thứ gì trong số này trong thời gian cố định. Ví dụ: hãy xem bản ghi thuộc tính đầu tiên.","metadata":{}},{"cell_type":"markdown","source":" truy vấn thông tin về thuộc tính của chú thích mẫu đầu tiên trong bảng sample_annotation. Trong bản ghi đó, trường attribute_tokens chứa danh sách mã định danh của các thuộc tính liên quan. Bằng cách truy cập vào phần tử đầu tiên của danh sách attribute_tokens và sử dụng phương thức get của LyftDataset, chúng ta có thể lấy lại thông tin về thuộc tính tương ứng.","metadata":{}},{"cell_type":"code","source":"lyftdata.get('attribute', lyftdata.sample_annotation[0]['attribute_tokens'][0])","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:42:38.187308Z","iopub.execute_input":"2023-06-05T14:42:38.187723Z","iopub.status.idle":"2023-06-05T14:42:38.196059Z","shell.execute_reply.started":"2023-06-05T14:42:38.187668Z","shell.execute_reply":"2023-06-05T14:42:38.195053Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Bản ghi thuộc tính chỉ ra trạng thái của đối tượng liên quan khi nó được chú thích.","metadata":{}},{"cell_type":"markdown","source":"Hãy bắt đầu với lược đồ cơ sở dữ liệu, từng cái một bắt đầu với `Scenes`","metadata":{}},{"cell_type":"markdown","source":"# **** 3/Lấy thông tin về một số đối tượng trong tập dữ liệu như danh sách các category, thông tin về một sample annotation, scene, attribute, instance, v.v.","metadata":{}},{"cell_type":"markdown","source":"Scene: Scene đề cập đến một khung cảnh (frame) hoặc một tập hợp các khung cảnh trong tập dữ liệu. Nó đại diện cho một thời điểm cụ thể trong quá trình quan sát và ghi lại môi trường xung quanh phương tiện. Mỗi scene có thể bao gồm các dữ liệu đa dạng như hình ảnh, dữ liệu LiDAR, dữ liệu radar và các thông tin khác về môi trường giao thông.","metadata":{}},{"cell_type":"markdown","source":"# Scenes\n\nMột cảnh là một chuỗi các khung hình liên tiếp dài 25-45 giây được trích xuất từ ​​​​nhật ký. Khung (còn được gọi là `mẫu`) là tập hợp các đầu ra của cảm biến (hình ảnh, điểm ảnh) tại một dấu thời gian nhất định\n\n\n```\nscene {\n   \"token\":                   <str> -- Unique record identifier.\n   \"name\":                    <str> -- Short string identifier.\n   \"description\":             <str> -- Longer description of the scene.\n   \"log_token\":               <str> -- Foreign key. Points to log from where the data was extracted.\n   \"nbr_samples\":             <int> -- Number of samples in this scene.\n   \"first_sample_token\":      <str> -- Foreign key. Points to the first sample in scene.\n   \"last_sample_token\":       <str> -- Foreign key. Points to the last sample in scene.\n}\n```","metadata":{}},{"cell_type":"markdown","source":"cách truy cập vào bản ghi đầu tiên trong bảng scene. Mỗi bản ghi trong bảng này chứa thông tin về một cảnh (giao lộ hoặc đoạn đường cụ thể) trong dữ liệu Lyft.","metadata":{}},{"cell_type":"code","source":"lyftdata.scene[0]","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:42:41.533932Z","iopub.execute_input":"2023-06-05T14:42:41.534565Z","iopub.status.idle":"2023-06-05T14:42:41.541810Z","shell.execute_reply.started":"2023-06-05T14:42:41.534490Z","shell.execute_reply":"2023-06-05T14:42:41.540825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Mỗi Scenes cung cấp mã thông báo mẫu đầu tiên và mã thông báo mẫu cuối cùng, chúng ta có thể thấy có 126 bản ghi mẫu (`nbr_samples`) ở giữa hai mã này.","metadata":{}},{"cell_type":"markdown","source":"### chúng ta hãy nhìn vào train.csv","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv('../input/3d-object-detection-for-autonomous-vehicles/train.csv')\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:44:10.121298Z","iopub.execute_input":"2023-06-05T14:44:10.121863Z","iopub.status.idle":"2023-06-05T14:44:10.829220Z","shell.execute_reply.started":"2023-06-05T14:44:10.121784Z","shell.execute_reply":"2023-06-05T14:44:10.828312Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Cột `Id` của khung dữ liệu đào tạo chứa các mã thông báo (số nhận dạng duy nhất) của các bản ghi mẫu đào tạo có trong bảng `sample` và `PredictionString` chứa các chú thích sự thật cơ bản tương ứng (hộp giới hạn) cho các loại đối tượng khác nhau","metadata":{}},{"cell_type":"code","source":"token0 = train.iloc[0]['Id']\ntoken0","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:45:07.723157Z","iopub.execute_input":"2023-06-05T14:45:07.723905Z","iopub.status.idle":"2023-06-05T14:45:07.731900Z","shell.execute_reply.started":"2023-06-05T14:45:07.723843Z","shell.execute_reply":"2023-06-05T14:45:07.730423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Chúng tôi sẽ sử dụng `token0` làm mã thông báo mẫu tham khảo của chúng tôi","metadata":{}},{"cell_type":"markdown","source":"# Sample","metadata":{}},{"cell_type":"markdown","source":"`sample` được định nghĩa là một khung hình chính có chú thích của một `scene` tại một dấu thời gian nhất định. Mẫu là dữ liệu được thu thập tại (xấp xỉ) cùng một dấu thời gian như một phần của một lần quét LIDAR.\n\n```\nsample {\n   \"token\":                   <str> -- Unique record identifier.\n   \"timestamp\":               <int> -- Unix time stamp.\n   \"scene_token\":             <str> -- Foreign key pointing to the scene.\n   \"next\":                    <str> -- Foreign key. Sample that follows this in time. Empty if end of scene.\n   \"prev\":                    <str> -- Foreign key. Sample that precedes this in time. Empty if start of scene.\n}\n```","metadata":{}},{"cell_type":"markdown","source":"Hãy nhớ rằng, `token0` là mã thông báo cho một bản ghi mẫu cụ thể trong bảng dữ liệu `sample` (`sample.json`), hãy cùng xem xét mẫu đó bằng hàm `.get` có sẵn của lyft SDK","metadata":{}},{"cell_type":"code","source":"my_sample = lyftdata.get('sample', token0)\nmy_sample","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:45:30.815849Z","iopub.execute_input":"2023-06-05T14:45:30.816363Z","iopub.status.idle":"2023-06-05T14:45:30.824487Z","shell.execute_reply.started":"2023-06-05T14:45:30.816316Z","shell.execute_reply":"2023-06-05T14:45:30.823333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Trực quan hóa tương tác 3D của một mẫu","metadata":{}},{"cell_type":"markdown","source":"Chúng tôi có thể trực quan hóa một mẫu một cách tương tác bằng cách sử dụng chức năng `render_sample_3d_interactive` có sẵn của lyft SDK","metadata":{}},{"cell_type":"code","source":"lyftdata.render_sample_3d_interactive(my_sample['token'], render_sample=False)","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:46:02.436951Z","iopub.execute_input":"2023-06-05T14:46:02.437414Z","iopub.status.idle":"2023-06-05T14:46:05.617735Z","shell.execute_reply.started":"2023-06-05T14:46:02.437345Z","shell.execute_reply":"2023-06-05T14:46:05.616440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Hãy xem chúng ta có gì khác ..","metadata":{}},{"cell_type":"code","source":"my_sample.keys()","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:47:05.385853Z","iopub.execute_input":"2023-06-05T14:47:05.386281Z","iopub.status.idle":"2023-06-05T14:47:05.393419Z","shell.execute_reply.started":"2023-06-05T14:47:05.386213Z","shell.execute_reply":"2023-06-05T14:47:05.391963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Vì vậy, `token0` của chúng tôi trỏ đến bản ghi `my_sample` trong bảng dữ liệu `sample`. Bản ghi mẫu này có 7 hình ảnh camera và 3 tệp dữ liệu LIDAR, có thể được tìm nạp bằng cách sử dụng mã thông báo tương ứng của chúng, từ đâu? không gì khác ngoài bảng `sample_data`.","metadata":{}},{"cell_type":"markdown","source":"# Sample data","metadata":{}},{"cell_type":"markdown","source":"`sample_data` là dữ liệu cảm biến, ví dụ: ảnh hoặc đám mây điểm.\n\n```\nsample_data {\n   \"token\":                   <str> -- Unique record identifier.\n   \"sample_token\":            <str> -- Foreign key. Sample to which this sample_data is associated.\n   \"ego_pose_token\":          <str> -- Foreign key.\n   \"calibrated_sensor_token\": <str> -- Foreign key.\n   \"filename\":                <str> -- Relative path to data-blob on disk.\n   \"fileformat\":              <str> -- Data file format.\n   \"width\":                   <int> -- If the sample data is an image, this is the image width in pixels.\n   \"height\":                  <int> -- If the sample data is an image, this is the image height in pixels.\n   \"timestamp\":               <int> -- Unix time stamp.\n   \"is_key_frame\":            <bool> -- True if sample_data is part of key_frame, else False.\n   \"next\":                    <str> -- Foreign key. Sample data from the same sensor that follows this in time. Empty if end of scene.\n   \"prev\":                    <str> -- Foreign key. Sample data from the same sensor that precedes this in time. Empty if start of scene.\n}\n```","metadata":{}},{"cell_type":"markdown","source":"Bộ dữ liệu chứa dữ liệu được thu thập từ bộ cảm biến đầy đủ. Do đó, đối với mỗi ảnh chụp nhanh của một cảnh, chúng tôi được cung cấp các tham chiếu đến một họ dữ liệu được thu thập từ các cảm biến này.","metadata":{}},{"cell_type":"markdown","source":"Bộ cảm biến đầy đủ bao gồm:\n* 7 cameras,\n* 3 LIDARs","metadata":{}},{"cell_type":"code","source":"lyftdata.sensor","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:48:12.532148Z","iopub.execute_input":"2023-06-05T14:48:12.532635Z","iopub.status.idle":"2023-06-05T14:48:12.540392Z","shell.execute_reply.started":"2023-06-05T14:48:12.532557Z","shell.execute_reply":"2023-06-05T14:48:12.539255Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Chúng tôi có thể sử dụng khóa `data` của một mẫu nhất định để truy cập một trong số này, chẳng hạn như:","metadata":{}},{"cell_type":"code","source":"sensor = 'CAM_FRONT'\ncam_front = lyftdata.get('sample_data', my_sample['data'][sensor])\ncam_front","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:48:16.161582Z","iopub.execute_input":"2023-06-05T14:48:16.161967Z","iopub.status.idle":"2023-06-05T14:48:16.169908Z","shell.execute_reply.started":"2023-06-05T14:48:16.161911Z","shell.execute_reply":"2023-06-05T14:48:16.168709Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Mỗi `sample_data` đều có một bản ghi của `sensor` mà từ đó dữ liệu được thu thập (lưu ý phím \"channel\"). Hãy xem hình ảnh được chụp bởi camera trước (CAM_FRONT)","metadata":{}},{"cell_type":"code","source":"img = Image.open(cam_front['filename'])\nimg","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:48:51.051143Z","iopub.execute_input":"2023-06-05T14:48:51.051525Z","iopub.status.idle":"2023-06-05T14:48:51.538349Z","shell.execute_reply.started":"2023-06-05T14:48:51.051465Z","shell.execute_reply":"2023-06-05T14:48:51.537336Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Chúng tôi cũng có thể sử dụng `render_sample_data` có sẵn của SDK để trực quan hóa dữ liệu `cam_front` (hãy nhớ `cam_front` là một bản ghi trong bảng `sample_data`)","metadata":{}},{"cell_type":"code","source":"lyftdata.render_sample_data(cam_front['token'], with_anns=False)","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:49:12.755069Z","iopub.execute_input":"2023-06-05T14:49:12.755489Z","iopub.status.idle":"2023-06-05T14:49:13.257900Z","shell.execute_reply.started":"2023-06-05T14:49:12.755419Z","shell.execute_reply":"2023-06-05T14:49:13.256698Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"chúng ta hãy xem dữ liệu LIDAR được liên kết với `my_sample`","metadata":{}},{"cell_type":"code","source":"lidar_top = lyftdata.get('sample_data', my_sample['data']['LIDAR_TOP']) # selecting LIDAR_TOP out of all LIDARs\nlidar_top","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:49:36.733706Z","iopub.execute_input":"2023-06-05T14:49:36.734135Z","iopub.status.idle":"2023-06-05T14:49:36.741539Z","shell.execute_reply.started":"2023-06-05T14:49:36.734065Z","shell.execute_reply":"2023-06-05T14:49:36.740611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Chúng ta có thể sử dụng `LidarPointCloud` để đọc các tệp dữ liệu LIDAR","metadata":{}},{"cell_type":"code","source":"pc = LidarPointCloud.from_file(Path(lidar_top['filename']))","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:49:54.473275Z","iopub.execute_input":"2023-06-05T14:49:54.473808Z","iopub.status.idle":"2023-06-05T14:49:54.479685Z","shell.execute_reply.started":"2023-06-05T14:49:54.473757Z","shell.execute_reply":"2023-06-05T14:49:54.478604Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pc.points.shape # x, y, z, intensity","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:49:56.480027Z","iopub.execute_input":"2023-06-05T14:49:56.480416Z","iopub.status.idle":"2023-06-05T14:49:56.486430Z","shell.execute_reply.started":"2023-06-05T14:49:56.480359Z","shell.execute_reply":"2023-06-05T14:49:56.485440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Hãy hình dung những điểm này","metadata":{}},{"cell_type":"markdown","source":"Đoạn mã SAU ĐÂY mô tả một hàm display_frame_statistics trong tập dữ liệu Lyft để hiển thị thông tin thống kê về một khung hình cụ thể. Hàm này vẽ biểu đồ 3D của dữ liệu điểm LiDAR và các chiếu dữ liệu điểm vào các mặt phẳng khác nhau.\n\naxes_limits là một danh sách chứa giới hạn của các trục tọa độ, bao gồm giới hạn của trục X, trục Y và trục Z. Ví dụ: [-30, 50] là giới hạn của trục X, [-30, 20] là giới hạn của trục Y và [-3, 10] là giới hạn của trục Z.\n\naxes_str là một danh sách chứa các chuỗi đại diện cho các trục tọa độ, bao gồm trục X, trục Y và trục Z. Ví dụ: 'X' đại diện cho trục X, 'Y' đại diện cho trục Y và 'Z' đại diện cho trục Z.\n\nHàm display_frame_statistics nhận vào tham số lidar_points, là dữ liệu điểm LiDAR, và points (mặc định là 0.2), đại diện cho tỷ lệ phần trăm các điểm LiDAR được sử dụng. Hàm này được sử dụng để hiển thị các thông số thống kê và biểu đồ của dữ liệu điểm LiDAR trong một khung hình cụ thể.\n\nHàm draw_point_cloud là một phương thức thuận tiện để vẽ các chiếu của dữ liệu điểm vào các mặt phẳng khác nhau. Nó nhận các tham số ax (trục), title (tiêu đề) và axes (trục tọa độ). Phương thức này được sử dụng để vẽ các chiếu dữ liệu điểm LiDAR vào các mặt phẳng 2D hoặc 3D.\n\nTrong đoạn mã, hàm display_frame_statistics vẽ dữ liệu điểm LiDAR dưới dạng biểu đồ 3D và các chiếu của dữ liệu điểm vào các mặt phẳng. Biểu đồ 3D được vẽ bằng cách sử dụng matplotlib và có các trục tọa độ X, Y, Z. Các chiếu dữ liệu điểm LiDAR vào các mặt phẳng XZ, XY và YZ cũng được vẽ bằng matplotlib.\n\nSau khi vẽ xong, các biểu đồ được hiển thị bằng matplotlib thông qua hàm plt.show().","metadata":{}},{"cell_type":"code","source":"axes_limits = [\n    [-30, 50], # X axis range\n    [-30, 20], # Y axis range\n    [-3, 10]   # Z axis range\n]\naxes_str = ['X', 'Y', 'Z']\n\ndef display_frame_statistics(lidar_points, points=0.2):\n    \"\"\"\n    Displays statistics for a single frame. Draws 3D plot of the lidar point cloud data and point cloud\n    projections to various planes.\n    \n    Parameters\n    ----------\n    lidar_points: lidar data points \n    points          : Fraction of lidar points to use. Defaults to `0.2`, e.g. 20%.\n    \"\"\"\n    \n    points_step = int(1. / points)\n    point_size = 0.01 * (1. / points)\n    pc_range = range(0, lidar_points.shape[1], points_step)\n    pc_frame = lidar_points[:, pc_range]\n    def draw_point_cloud(ax, title, axes=[0, 1, 2]):\n        \"\"\"Convenient method for drawing various point cloud projections as a part of frame statistics\"\"\"\n        ax.set_facecolor('black')\n        ax.grid(False)\n        ax.scatter(*pc_frame[axes, :], s=point_size, c='white', cmap='grey')\n        if len(axes) == 3: # 3D configs\n            text_color = 'white'\n            ax.set_xlim3d([-10, 30])\n            ax.set_ylim3d(*axes_limits[axes[1]])\n            ax.set_zlim3d(*axes_limits[axes[2]])\n            ax.set_zlabel('{} axis'.format(axes_str[axes[2]]), color='white')\n        else: # 2D configs\n            text_color = 'black' # the `figure` is white\n            ax.set_xlim(*axes_limits[axes[0]])\n            ax.set_ylim(*axes_limits[axes[1]])\n        ax.set_title(title, color=text_color)\n        ax.set_xlabel('{} axis'.format(axes_str[axes[0]]), color=text_color)\n        ax.set_ylabel('{} axis'.format(axes_str[axes[1]]), color=text_color)\n            \n    # Draw point cloud data as 3D plot\n    f2 = plt.figure(figsize=(15, 8))\n    ax2 = f2.add_subplot(111, projection='3d')\n    # make the panes transparent\n    ax2.xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))\n    ax2.yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))\n    ax2.zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))\n    draw_point_cloud(ax2, '3D plot')\n    \n    plt.show()\n    plt.close(f2)\n    # Draw point cloud data as plane projections\n    f, ax3 = plt.subplots(3, 1, figsize=(15, 25))\n#     f.set_facecolor('black')\n    draw_point_cloud(\n        ax3[0], \n        'XZ projection (Y = 0)', #, the car is moving in direction left to right', ?\n        axes=[0, 2] # X and Z axes\n    )\n    draw_point_cloud(\n        ax3[1], \n        'XY projection (Z = 0)', #, the car is moving in direction left to right',? \n        axes=[0, 1] # X and Y axes\n    )\n    draw_point_cloud(\n        ax3[2], \n        'YZ projection (X = 0)', #, the car is moving towards the graph plane', ?\n        axes=[1, 2] # Y and Z axes\n    )\n    plt.show()\n    plt.close(f)","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:50:08.078178Z","iopub.execute_input":"2023-06-05T14:50:08.078629Z","iopub.status.idle":"2023-06-05T14:50:08.105782Z","shell.execute_reply.started":"2023-06-05T14:50:08.078562Z","shell.execute_reply":"2023-06-05T14:50:08.104389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_frame_statistics(pc.points, points=0.5)","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:50:12.469733Z","iopub.execute_input":"2023-06-05T14:50:12.470369Z","iopub.status.idle":"2023-06-05T14:50:21.490549Z","shell.execute_reply.started":"2023-06-05T14:50:12.470289Z","shell.execute_reply":"2023-06-05T14:50:21.489337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Chúng tôi cũng có thể sử dụng `render_sample_data` có sẵn của SDK để trực quan hóa `lidar_top` (hãy nhớ `lidar_top` là một bản ghi trong bảng `sample_data`, giống như `cam_front` là)","metadata":{}},{"cell_type":"code","source":"lyftdata.render_sample_data(lidar_top['token'], with_anns=False)","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:51:14.986081Z","iopub.execute_input":"2023-06-05T14:51:14.986502Z","iopub.status.idle":"2023-06-05T14:51:20.572563Z","shell.execute_reply.started":"2023-06-05T14:51:14.986431Z","shell.execute_reply":"2023-06-05T14:51:20.571717Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Vì vậy, các sơ đồ trên hiển thị một cảm biến LIDAR cụ thể (`TOP_LIDAR`), Mỗi cảm biến được gắn trên một phương tiện bản ngã hay còn gọi là Xe tự trị (AV), ở đây có `ego_pose`","metadata":{}},{"cell_type":"markdown","source":"## ego_pose","metadata":{}},{"cell_type":"markdown","source":"`ego_pose` chứa thông tin về vị trí (được mã hóa trong `translation`) và hướng (được mã hóa trong `xoay`) của khung thân xe ego, đối với hệ tọa độ toàn cầu.","metadata":{}},{"cell_type":"code","source":"lyftdata.get('ego_pose', cam_front['ego_pose_token'])","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:51:39.544991Z","iopub.execute_input":"2023-06-05T14:51:39.545414Z","iopub.status.idle":"2023-06-05T14:51:39.552967Z","shell.execute_reply.started":"2023-06-05T14:51:39.545344Z","shell.execute_reply":"2023-06-05T14:51:39.551916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Các tham số ego_pose được sử dụng để đưa các điểm từ hệ tọa độ toàn cầu (giả sử các góc của hộp giới hạn) sang hệ quy chiếu của phương tiện tự ngã. Như chúng ta đã biết mỗi xe ego có rất nhiều cảm biến, mỗi cảm biến có một số thông số cân chỉnh w.r.t xe ego","metadata":{}},{"cell_type":"markdown","source":"## caliberated_sensor","metadata":{}},{"cell_type":"markdown","source":"`caliberated_sensor` bao gồm định nghĩa của một cảm biến cụ thể (lidar/radar/máy ảnh) được hiệu chỉnh trên một phương tiện cụ thể. Chúng ta hãy xem xét một ví dụ.","metadata":{}},{"cell_type":"code","source":"lyftdata.get('calibrated_sensor', cam_front['calibrated_sensor_token'])","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:52:44.860688Z","iopub.execute_input":"2023-06-05T14:52:44.861228Z","iopub.status.idle":"2023-06-05T14:52:44.869415Z","shell.execute_reply.started":"2023-06-05T14:52:44.861154Z","shell.execute_reply":"2023-06-05T14:52:44.867751Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Tất cả các thông số bên ngoài được đưa ra đối với khung thân xe bản ngã. Chúng tôi sử dụng các thông số của caliberate_sensor để đưa các điểm từ hệ quy chiếu của xe tự ngã sang hệ quy chiếu của cảm biến. Nó được sử dụng để vẽ các hộp giới hạn trong hình ảnh và đám mây điểm lidar.","metadata":{}},{"cell_type":"markdown","source":"Chúng ta sẽ cần hiệu chỉnh cảm biến và tham số ego_pose khi vẽ các hộp giới hạn cùng với đám mây điểm lidar. Chúng ta sẽ thấy điều này sau, trước đó, hãy hình dung những thứ khác mà `my_sample` có, bắt đầu với chú thích hộp giới hạn","metadata":{}},{"cell_type":"markdown","source":"# Annotations","metadata":{}},{"cell_type":"markdown","source":"Thông tin về một sample annotation: Một sample annotation cung cấp thông tin chi tiết về một đối tượng cụ thể trong tập dữ liệu. Thông tin này thường bao gồm tọa độ 3D (x, y, z) của đối tượng, hình dạng và kích thước của nó, và các thuộc tính khác như tốc độ, hướng di chuyển, lớp (category) của đối tượng đó. Ví dụ, một sample annotation có thể đại diện cho một xe với tọa độ và kích thước cụ thể, cùng với các thuộc tính như tốc độ và hướng di chuyển của xe đó.","metadata":{}},{"cell_type":"markdown","source":"`sample_annotation` đề cập đến một hộp giới hạn xác định vị trí của một đối tượng được nhìn thấy trong một mẫu.\nTất cả dữ liệu vị trí được cung cấp đối với hệ tọa độ toàn cầu.\n```\nsample_annotation {\n   \"token\":                   <str> -- Unique record identifier.\n   \"sample_token\":            <str> -- Foreign key. NOTE: this points to a sample NOT a sample_data since annotations are done on the sample level taking all relevant sample_data into account.\n   \"instance_token\":          <str> -- Foreign key. Which object instance is this annotating. An instance can have multiple annotations over time.\n   \"attribute_tokens\":        <str> [n] -- Foreign keys. List of attributes for this annotation. Attributes can change over time, so they belong here, not in the object table.\n   \"visibility_token\":        <str> -- Foreign key. Visibility may also change over time. If no visibility is annotated, the token is an empty string.\n   \"translation\":             <float> [3] -- Bounding box location in meters as center_x, center_y, center_z.\n   \"size\":                    <float> [3] -- Bounding box size in meters as width, length, height.\n   \"rotation\":                <float> [4] -- Bounding box orientation as quaternion: w, x, y, z.\n   \"num_lidar_pts\":           <int> -- Number of lidar points in this box. Points are counted during the lidar sweep identified with this sample.\n   \"num_radar_pts\":           <int> -- Number of radar points in this box. Points are counted during the radar sweep identified with this sample. This number is summed across all radar sensors without any invalid point filtering.\n   \"next\":                    <str> -- Foreign key. Sample annotation from the same object instance that follows this in time. Empty if this is the last annotation for this object.\n   \"prev\":                    <str> -- Foreign key. Sample annotation from the same object instance that precedes this in time. Empty if this is the first annotation for this object.\n}\n```","metadata":{}},{"cell_type":"code","source":"my_annotation = lyftdata.get('sample_annotation', my_sample['anns'][0])\nmy_annotation","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:53:31.922023Z","iopub.execute_input":"2023-06-05T14:53:31.922707Z","iopub.status.idle":"2023-06-05T14:53:31.930482Z","shell.execute_reply.started":"2023-06-05T14:53:31.922646Z","shell.execute_reply":"2023-06-05T14:53:31.929471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Mỗi chú thích có tất cả dữ liệu vị trí đối với hệ tọa độ toàn cầu. Chúng tôi sẽ phải quan tâm đến việc xoay, dịch và kích thước trước khi hoàn thiện tọa độ hộp giới hạn cuối cùng trên các hình ảnh mẫu, may mắn thay, chúng tôi có một chức năng sẵn có cho điều đó","metadata":{}},{"cell_type":"code","source":"my_box = lyftdata.get_box(my_annotation['token'])\nmy_box # Box class instance","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:53:35.836431Z","iopub.execute_input":"2023-06-05T14:53:35.836815Z","iopub.status.idle":"2023-06-05T14:53:35.844549Z","shell.execute_reply.started":"2023-06-05T14:53:35.836746Z","shell.execute_reply":"2023-06-05T14:53:35.843283Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"my_box.center, my_box.wlh # center coordinates + width, length and height","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:53:38.511119Z","iopub.execute_input":"2023-06-05T14:53:38.511769Z","iopub.status.idle":"2023-06-05T14:53:38.520549Z","shell.execute_reply.started":"2023-06-05T14:53:38.511692Z","shell.execute_reply":"2023-06-05T14:53:38.519111Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Hãy xem `my_annotation` của chúng ta (hãy nhớ rằng đây là một chú thích đối tượng duy nhất trong số nhiều chú thích có trong `my_sample`) bằng cách sử dụng chức năng `render_annotation` có sẵn của SDK","metadata":{}},{"cell_type":"code","source":"lyftdata.render_annotation(my_annotation['token'], margin=10)","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:53:42.789150Z","iopub.execute_input":"2023-06-05T14:53:42.789693Z","iopub.status.idle":"2023-06-05T14:53:48.093658Z","shell.execute_reply.started":"2023-06-05T14:53:42.789642Z","shell.execute_reply":"2023-06-05T14:53:48.092570Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Mỗi chú thích có một `thuộc tính`:","metadata":{}},{"cell_type":"markdown","source":"# Attributes","metadata":{}},{"cell_type":"markdown","source":"Attribute: Attribute liên quan đến các thuộc tính của đối tượng trong tập dữ liệu. Nó mô tả các đặc điểm, tính chất hoặc trạng thái của đối tượng mà không thuộc vào loại (category) của nó. Ví dụ, một attribute có thể đại diện cho trạng thái đèn giao thông (đèn đỏ, đèn xanh, v.v.), tình trạng của xe (dừng, di chuyển, v.v.) hoặc tình trạng của người đi bộ (đang băng qua đường, đứng yên, v.v.). Attributes cung cấp thông tin phụ cho việc mô tả và hiểu cách các đối tượng trong môi trường giao thông hoạt động.","metadata":{}},{"cell_type":"markdown","source":"Attribute của một thể hiện có thể thay đổi trong khi danh mục vẫn giữ nguyên.\n Ví dụ: một phương tiện đang đỗ/dừng/di chuyển và xe đạp có người lái hay không.\n```\nattribute {\n   \"token\":                   <str> -- Unique record identifier.\n   \"name\":                    <str> -- Attribute name.\n   \"description\":             <str> -- Attribute description.\n}\n```","metadata":{}},{"cell_type":"code","source":"my_attribute1 = lyftdata.get('attribute', my_annotation['attribute_tokens'][0])\nmy_attribute2 = lyftdata.get('attribute', my_annotation['attribute_tokens'][1])","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:55:54.192826Z","iopub.execute_input":"2023-06-05T14:55:54.193409Z","iopub.status.idle":"2023-06-05T14:55:54.199214Z","shell.execute_reply.started":"2023-06-05T14:55:54.193112Z","shell.execute_reply":"2023-06-05T14:55:54.197838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"my_attribute1","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:55:56.217252Z","iopub.execute_input":"2023-06-05T14:55:56.217607Z","iopub.status.idle":"2023-06-05T14:55:56.224934Z","shell.execute_reply.started":"2023-06-05T14:55:56.217562Z","shell.execute_reply":"2023-06-05T14:55:56.223303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"my_attribute2","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:55:57.984654Z","iopub.execute_input":"2023-06-05T14:55:57.985087Z","iopub.status.idle":"2023-06-05T14:55:57.991847Z","shell.execute_reply.started":"2023-06-05T14:55:57.985022Z","shell.execute_reply":"2023-06-05T14:55:57.990775Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Có vẻ như đối tượng của chúng tôi đang bế tắc","metadata":{}},{"cell_type":"markdown","source":"# Instances","metadata":{}},{"cell_type":"markdown","source":"Instance: Instance đề cập đến một phiên bản cụ thể của một đối tượng trong tập dữ liệu. Nó biểu thị các trường hợp riêng biệt của các đối tượng cùng loại (cùng category). Ví dụ, nếu trong một khung cảnh có nhiều xe, mỗi xe sẽ được coi là một instance riêng biệt. Mỗi instance có thể có các thông tin riêng, chẳng hạn như tọa độ và kích thước đối tượng, thuộc tính và các thông tin khác về trạng thái và hành vi của đối tượng đó.","metadata":{}},{"cell_type":"markdown","source":"Phiên bản đối tượng là các phiên bản cần được phát hiện hoặc theo dõi bởi một phương tiện tự động (ví dụ: một phương tiện cụ thể, người đi bộ). Hãy để chúng tôi kiểm tra một siêu dữ liệu ví dụ","metadata":{}},{"cell_type":"code","source":"my_instance = lyftdata.get('instance', my_annotation['instance_token'])\nmy_instance","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:56:24.415064Z","iopub.execute_input":"2023-06-05T14:56:24.415954Z","iopub.status.idle":"2023-06-05T14:56:24.425623Z","shell.execute_reply.started":"2023-06-05T14:56:24.415825Z","shell.execute_reply":"2023-06-05T14:56:24.423834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lyftdata.render_instance(my_instance['token'])","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:56:27.576694Z","iopub.execute_input":"2023-06-05T14:56:27.577152Z","iopub.status.idle":"2023-06-05T14:56:33.195999Z","shell.execute_reply.started":"2023-06-05T14:56:27.577070Z","shell.execute_reply":"2023-06-05T14:56:33.195030Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Mọi người thường theo dõi một phiên bản trên các khung hình khác nhau trong một cảnh cụ thể. Đó là lý do tại sao chúng tôi có `first_annotation_token` và `last_annotation_token` trong `my_instance`","metadata":{}},{"cell_type":"code","source":"print(\"First annotated sample of this instance:\")\nlyftdata.render_annotation(my_instance['first_annotation_token'])","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:57:03.991083Z","iopub.execute_input":"2023-06-05T14:57:03.991604Z","iopub.status.idle":"2023-06-05T14:57:09.337227Z","shell.execute_reply.started":"2023-06-05T14:57:03.991460Z","shell.execute_reply":"2023-06-05T14:57:09.336357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Last annotated sample of this instance\")\nlyftdata.render_annotation(my_instance['last_annotation_token'])","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:57:09.338846Z","iopub.execute_input":"2023-06-05T14:57:09.339300Z","iopub.status.idle":"2023-06-05T14:57:14.461413Z","shell.execute_reply.started":"2023-06-05T14:57:09.339254Z","shell.execute_reply":"2023-06-05T14:57:14.460259Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Cho đến nay, chúng ta đã thấy rằng mỗi điểm dữ liệu mẫu có một loạt hình ảnh được chụp từ các máy ảnh khác nhau, một loạt điểm dữ liệu lidar được lấy từ các cảm biến lidar khác nhau, nó có chú thích cho các đối tượng trong những hình ảnh đó, các thuộc tính được liên kết với các chú thích đó. Hãy trực quan hóa mọi thứ mà điểm dữ liệu này có trong chính nó bằng cách sử dụng chức năng `render_sample` inbuit của SDK","metadata":{}},{"cell_type":"code","source":"lyftdata.render_sample(token0)","metadata":{"execution":{"iopub.status.busy":"2023-06-05T14:57:21.293062Z","iopub.execute_input":"2023-06-05T14:57:21.293439Z","iopub.status.idle":"2023-06-05T14:57:44.674022Z","shell.execute_reply.started":"2023-06-05T14:57:21.293382Z","shell.execute_reply":"2023-06-05T14:57:44.672248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Trực quan hóa 3D của một scene","metadata":{}},{"cell_type":"code","source":"my_scene = lyftdata.get('scene',  my_sample['scene_token'])","metadata":{"execution":{"iopub.status.busy":"2023-06-05T15:00:21.899266Z","iopub.execute_input":"2023-06-05T15:00:21.899713Z","iopub.status.idle":"2023-06-05T15:00:21.905347Z","shell.execute_reply.started":"2023-06-05T15:00:21.899662Z","shell.execute_reply":"2023-06-05T15:00:21.904129Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Hãy trực quan hóa `LIDAR_TOP` của tất cả các mẫu của `my_scene` của chúng ta ở chế độ 3D. Đây là cách chúng ta sẽ làm điều này:\n* Mỗi đám mây điểm lidar nằm trong hệ quy chiếu của [lidar ranger](https://en.wikipedia.org/wiki/Laser_rangefinder), chúng ta phải lấy từng điểm trong hệ quy chiếu của phương tiện.\n* Mỗi góc của hộp giới hạn nằm trong hệ tọa độ toàn cầu, chúng tôi đưa chúng vào hệ quy chiếu phương tiện tự ngã bằng cách sử dụng tham số ego_pose.\n* Khi chúng ta có điểm nắp và góc hộp trong hệ quy chiếu của xe, chúng ta vẽ các điểm bằng chức năng phân tán của matplotlib và vẽ các cạnh hộp bằng chức năng vẽ đồ thị của matplotlib","metadata":{}},{"cell_type":"code","source":"def get_lidar_points(lidar_token):\n    '''Get lidar point cloud in the frame of the ego vehicle'''\n    sd_record = lyftdata.get(\"sample_data\", lidar_token)\n    sensor_modality = sd_record[\"sensor_modality\"]\n    \n    # Get aggregated point cloud in lidar frame.\n    sample_rec = lyftdata.get(\"sample\", sd_record[\"sample_token\"])\n    chan = sd_record[\"channel\"]\n    ref_chan = \"LIDAR_TOP\"\n    pc, times = LidarPointCloud.from_file_multisweep(\n        lyftdata, sample_rec, chan, ref_chan, num_sweeps=1\n    )\n    # Compute transformation matrices for lidar point cloud\n    cs_record = lyftdata.get(\"calibrated_sensor\", sd_record[\"calibrated_sensor_token\"])\n    pose_record = lyftdata.get(\"ego_pose\", sd_record[\"ego_pose_token\"])\n    vehicle_from_sensor = np.eye(4)\n    vehicle_from_sensor[:3, :3] = Quaternion(cs_record[\"rotation\"]).rotation_matrix\n    vehicle_from_sensor[:3, 3] = cs_record[\"translation\"]\n    \n    ego_yaw = Quaternion(pose_record[\"rotation\"]).yaw_pitch_roll[0]\n    rot_vehicle_flat_from_vehicle = np.dot(\n        Quaternion(scalar=np.cos(ego_yaw / 2), vector=[0, 0, np.sin(ego_yaw / 2)]).rotation_matrix,\n        Quaternion(pose_record[\"rotation\"]).inverse.rotation_matrix,\n    )\n    vehicle_flat_from_vehicle = np.eye(4)\n    vehicle_flat_from_vehicle[:3, :3] = rot_vehicle_flat_from_vehicle\n    points = view_points(\n        pc.points[:3, :], np.dot(vehicle_flat_from_vehicle, vehicle_from_sensor), normalize=False\n    )\n    return points","metadata":{"execution":{"iopub.status.busy":"2023-06-05T15:00:53.491508Z","iopub.execute_input":"2023-06-05T15:00:53.491962Z","iopub.status.idle":"2023-06-05T15:00:53.507124Z","shell.execute_reply.started":"2023-06-05T15:00:53.491889Z","shell.execute_reply":"2023-06-05T15:00:53.505804Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Đoạn mã trên mô tả hàm get_lidar_points(lidar_token) trong tập dữ liệu Lyft. Hàm này được sử dụng để lấy dữ liệu điểm LiDAR trong khung hình của phương tiện ego.\n\nHàm nhận vào một tham số lidar_token, đại diện cho mã thông tin của dữ liệu điểm LiDAR.\n\nĐầu tiên, hàm lấy thông tin ghi chú (record) của dữ liệu sensor tương ứng với lidar_token thông qua lời gọi lyftdata.get(\"sample_data\", lidar_token). Trong đoạn mã, thông tin này được gán cho biến sd_record.\n\nTiếp theo, hàm lấy thông tin ghi chú của mẫu (sample) chứa dữ liệu điểm LiDAR thông qua lời gọi lyftdata.get(\"sample\", sd_record[\"sample_token\"]). Kết quả được gán cho biến sample_rec.\n\nSau đó, hàm lấy tên kênh (channel) của dữ liệu điểm LiDAR từ sd_record[\"channel\"] và tên kênh tham chiếu (reference channel) là \"LIDAR_TOP\" thông qua lời gọi ref_chan = \"LIDAR_TOP\".\n\nHàm sử dụng phương thức LidarPointCloud.from_file_multisweep() để lấy điểm điện LiDAR trong khung hình của phương tiện ego. Phương thức này nhận các tham số lyftdata (tập dữ liệu Lyft), sample_rec (thông tin ghi chú của mẫu), chan (tên kênh), ref_chan (tên kênh tham chiếu), và num_sweeps (số lượt quét). Kết quả trả về là pc (điểm điện LiDAR) và times (thời gian).\n\nTiếp theo, hàm lấy thông tin ghi chú của cảm biến hiệu chuẩn (calibrated sensor) thông qua lời gọi lyftdata.get(\"calibrated_sensor\", sd_record[\"calibrated_sensor_token\"]). Thông tin này được gán cho biến cs_record.\n\nHàm cũng lấy thông tin ghi chú về tọa độ của phương tiện ego (ego pose) thông qua lời gọi lyftdata.get(\"ego_pose\", sd_record[\"ego_pose_token\"]). Thông tin này được gán cho biến pose_record.\n\nTiếp theo, hàm tính toán ma trận biến đổi cho dữ liệu điểm LiDAR trong khung hình của phương tiện. Đầu tiên, nó tạo ma trận vehicle_from_sensor kích thước 4x4 bằng ma trận đơn vị. Sau đó, nó cập nhật ma trận này với thông tin về quay và dịch chuyển từ cs_record. Thông tin về quay được chuyển thành ma trận quay bằng cách sử dụng Quaternion(cs_record[\"rotation\"]).rotation_matrix và được gán cho phần tử trên đường chéo chính của vehicle_from_sensor. Thông tin về dịch chuyển được gán cho phần tử tương ứng của vehicle_from_sensor.\n\nHàm tính toán giá trị yaw của phương tiện ego thông qua Quaternion(pose_record[\"rotation\"]).yaw_pitch_roll[0] và gán cho biến ego_yaw.\n\nHàm tính toán ma trận rot_vehicle_flat_from_vehicle bằng cách kết hợp các ma trận quay để xác định ma trận biến đổi từ hệ tọa độ phẳng của phương tiện đến hệ tọa độ phẳng chứa phương tiện (xác định bởi ego_yaw).\n\nHàm tạo ma trận vehicle_flat_from_vehicle kích thước 4x4 bằng ma trận đơn vị và cập nhật ma trận này với thông tin biến đổi rot_vehicle_flat_from_vehicle.\n\nCuối cùng, hàm tính toán các điểm LiDAR trong khung hình của phương tiện bằng cách sử dụng view_points() với tham số pc.points[:3, :] (tọa độ X, Y, Z của các điểm LiDAR), ma trận biến đổi từ hệ tọa độ phẳng của phương tiện đến hệ tọa độ phẳng chứa phương tiện (np.dot(vehicle_flat_from_vehicle, vehicle_from_sensor)), và normalize=False. Kết quả trả về là points, chứa các điểm LiDAR trong khung hình của phương tiện ego.","metadata":{}},{"cell_type":"code","source":"def plot_box(box, axis, view, colors, normalize=False, linewidth=1.0):\n    '''Plot boxes in the 3d figure'''\n    corners = view_points(box.corners(), view, normalize=normalize)#\n    def draw_rect(selected_corners, color):\n        prev = selected_corners[-1]\n        for corner in selected_corners:\n            axis.plot([prev[0], corner[0]], [prev[1], corner[1]], [prev[2], corner[2]], color=color, linewidth=linewidth)\n            prev = corner\n\n    # Draw the sides\n    for i in range(4):\n        axis.plot(\n            [corners.T[i][0], corners.T[i + 4][0]],\n            [corners.T[i][1], corners.T[i + 4][1]],\n            [corners.T[i][2], corners.T[i + 4][2]],\n            color=colors[2],\n            linewidth=linewidth,\n        )\n\n    # Draw front (first 4 corners) and rear (last 4 corners) rectangles(3d)/lines(2d)\n    draw_rect(corners.T[:4], colors[0]) #4x3\n    draw_rect(corners.T[4:], colors[1])","metadata":{"execution":{"iopub.status.busy":"2023-06-05T15:00:56.841711Z","iopub.execute_input":"2023-06-05T15:00:56.842122Z","iopub.status.idle":"2023-06-05T15:00:56.857364Z","shell.execute_reply.started":"2023-06-05T15:00:56.842053Z","shell.execute_reply":"2023-06-05T15:00:56.855988Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\nĐoạn mã trên mô tả hàm plot_box(box, axis, view, colors, normalize=False, linewidth=1.0) trong tập dữ liệu Lyft. Hàm này được sử dụng để vẽ hình hộp (bounding box) trong hình 3D.\n\nHàm nhận vào các tham số:\n\nbox: đối tượng hình hộp (bounding box) chứa thông tin về tọa độ của các đỉnh.\naxis: đối tượng trục (axis) của hình 3D.\nview: ma trận biến đổi để chuyển đổi tọa độ đỉnh của hình hộp từ tọa độ thế giới sang tọa độ hiển thị trên hình 3D.\ncolors: danh sách màu sắc cho các phần của hình hộp.\nnormalize: cờ chỉ định xem liệu tọa độ đã được chuẩn hóa hay chưa. Mặc định là False.\nlinewidth: độ rộng của đường vẽ. Mặc định là 1.0.\nHàm sử dụng phương thức view_points() để chuyển đổi tọa độ các đỉnh của hình hộp từ tọa độ thế giới sang tọa độ hiển thị trên hình 3D. Kết quả được gán cho biến corners.\n\nHàm định nghĩa hàm draw_rect(selected_corners, color) để vẽ các đường thẳng hoặc hình chữ nhật trên hình 3D. Hàm này nhận vào danh sách các đỉnh selected_corners và màu sắc color.\n\nHàm sử dụng vòng lặp for để vẽ các đường thẳng đại diện cho các cạnh của hình hộp. Cụ thể, nó sử dụng phương thức plot() của đối tượng trục (axis) để vẽ các đường thẳng giữa các cặp đỉnh tương ứng.\n\nTiếp theo, hàm sử dụng phương thức draw_rect() để vẽ hình chữ nhật hoặc đường thẳng trước (4 đỉnh đầu tiên) và phía sau (4 đỉnh cuối cùng) của hình hộp.","metadata":{}},{"cell_type":"code","source":"def draw_3d_plot(idx, lidar_token):\n    '''Plot the lidar + annotations on a 3D figure'''\n    # sample lidar point cloud\n    lidar_points = get_lidar_points(lidar_token)\n    points = 0.5 # fraction of lidar_points to plot, to reduce the clutter\n    points_step = int(1. / points)\n    pc_range = range(0, lidar_points.shape[1], points_step)\n    lidar_points = lidar_points[:, pc_range]\n    \n    # Get boxes, instead of current sensor's coordinate frame, use vehicle frame which is aligned to z-plane in world\n    _, boxes, _ = lyftdata.get_sample_data(\n        lidar_token, flat_vehicle_coordinates=True\n    )\n    fig = plt.figure(figsize=(15, 8))\n    ax = fig.add_subplot(111, projection='3d')                    \n    point_size = 0.01 * (1. / points) # size of the dots on plot\n    ax.set_facecolor('black')\n    ax.grid(False)\n    ax.scatter(*lidar_points, s=point_size, c='white', cmap='gray')\n    for box in boxes:\n        c = np.array(lyftdata.explorer.get_color(box.name)) / 255.0\n        plot_box(box, ax, view=np.eye(3), colors=(c, c, c), linewidth=0.5)\n    ax.set_xlim3d(-40, 40)\n    ax.set_ylim3d(-40, 40)\n    ax.set_zlim3d(-4, 40)\n    \n    # make the panes transparent\n    ax.xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))\n    ax.yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))\n    ax.zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))\n    ax.set_title(lidar_token, color='white')\n    filename = 'tmp/frame_{0:0>4}.png'.format(idx)\n    plt.savefig(filename)\n    plt.close(fig)\n    return filename","metadata":{"execution":{"iopub.status.busy":"2023-06-05T15:00:59.799751Z","iopub.execute_input":"2023-06-05T15:00:59.800177Z","iopub.status.idle":"2023-06-05T15:00:59.817659Z","shell.execute_reply.started":"2023-06-05T15:00:59.800086Z","shell.execute_reply":"2023-06-05T15:00:59.816394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Đoạn mã trên mô tả hàm draw_3d_plot(idx, lidar_token) trong tập dữ liệu Lyft. Hàm này được sử dụng để vẽ hình 3D của dữ liệu LiDAR và các hình hộp (bounding box) tương ứng.\n\nHàm nhận vào hai tham số:\n\nidx: chỉ số của khung hình (frame).\nlidar_token: mã thông tin về dữ liệu LiDAR của khung hình (frame).\nĐầu tiên, hàm sử dụng hàm get_lidar_points(lidar_token) để lấy điểm dữ liệu LiDAR của khung hình. Tiếp theo, nó giới hạn số lượng điểm được sử dụng để vẽ hình 3D bằng cách chọn một phần tử từ lidar_points dựa trên points (một phần trăm số lượng điểm tương ứng với points).\n\nHàm sử dụng lyftdata.get_sample_data(lidar_token, flat_vehicle_coordinates=True) để lấy danh sách các hình hộp (bounding box) tương ứng với dữ liệu LiDAR.\n\nTiếp theo, hàm tạo một đối tượng hình 3D với kích thước và thiết lập mặc định.\n\nHàm sử dụng scatter() để vẽ các điểm dữ liệu LiDAR trên hình 3D. Màu sắc của điểm được đặt là trắng và kích thước của điểm được điều chỉnh bằng point_size.\n\nHàm sử dụng vòng lặp for để vẽ các hình hộp (bounding box) trên hình 3D. Mỗi hình hộp được tô màu dựa trên tên của nó, sử dụng lyftdata.explorer.get_color() và plot_box() được gọi để vẽ hình hộp đó.\n\nHàm thiết lập giới hạn trục cho hình 3D.\n\nHàm làm cho các bề mặt trong hình 3D trở nên trong suốt bằng cách đặt màu sắc alpha của các pane thành 0.\n\nHàm lưu hình 3D vào tệp PNG với tên tệp được xác định bởi filename.\n\nCuối cùng, hàm trả về tên tệp PNG của hình 3D vừa được lưu.","metadata":{}},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"!mkdir tmp # a temporary folder to contain plot jpegs","metadata":{"execution":{"iopub.status.busy":"2023-06-05T15:01:10.979843Z","iopub.execute_input":"2023-06-05T15:01:10.980378Z","iopub.status.idle":"2023-06-05T15:01:12.155190Z","shell.execute_reply.started":"2023-06-05T15:01:10.980200Z","shell.execute_reply":"2023-06-05T15:01:12.153810Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# let's take a quick look at the 3d Plot\nfirst_sample_token = my_scene['first_sample_token']\nsample = lyftdata.get('sample', first_sample_token)\nlidar_token = sample['data']['LIDAR_TOP']\nfilename = draw_3d_plot(0, lidar_token)\nImage.open(filename)","metadata":{"execution":{"iopub.status.busy":"2023-06-05T15:01:14.345410Z","iopub.execute_input":"2023-06-05T15:01:14.345971Z","iopub.status.idle":"2023-06-05T15:01:22.031548Z","shell.execute_reply.started":"2023-06-05T15:01:14.345914Z","shell.execute_reply":"2023-06-05T15:01:22.030373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Đoạn mã trên cho ta một cái nhìn nhanh về hình ảnh 3D được vẽ.\n\nĐầu tiên, ta lấy mã thông tin về khung hình đầu tiên trong cảnh (my_scene) bằng cách sử dụng khóa first_sample_token.\n\nTiếp theo, ta sử dụng mã thông tin này để lấy thông tin về mẫu (sample) từ tập dữ liệu Lyft bằng cách sử dụng hàm lyftdata.get('sample', first_sample_token).\n\nTa lấy mã thông tin về dữ liệu LiDAR của khung hình từ khóa data trong mẫu (sample['data']['LIDAR_TOP']).\n\nTiếp theo, ta gọi hàm draw_3d_plot(0, lidar_token) để vẽ hình ảnh 3D của dữ liệu LiDAR. Tham số 0 đại diện cho chỉ số của khung hình (frame), và lidar_token đại diện cho mã dữ liệu LiDAR của khung hình.\n\nHàm draw_3d_plot() sẽ trả về tên tệp PNG của hình ảnh 3D được lưu.\n\nCuối cùng, ta sử dụng Image.open(filename) để mở và hiển thị hình ảnh 3D.","metadata":{}},{"cell_type":"markdown","source":"Hãy hình dung `my_scene` ở dạng video","metadata":{}},{"cell_type":"code","source":"frames = []\nfirst_sample_token = my_scene['first_sample_token']\ntoken = first_sample_token\nfor i in tqdm(range(my_scene['nbr_samples'])):\n    sample = lyftdata.get('sample', token)\n    lidar_token = sample['data']['LIDAR_TOP']\n    filename = draw_3d_plot(i, lidar_token)\n    frames += [filename]\n    token = sample['next']\n#     break","metadata":{"execution":{"iopub.status.busy":"2023-06-05T15:01:50.925659Z","iopub.execute_input":"2023-06-05T15:01:50.926133Z","iopub.status.idle":"2023-06-05T15:17:41.922827Z","shell.execute_reply.started":"2023-06-05T15:01:50.926039Z","shell.execute_reply":"2023-06-05T15:17:41.921690Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\nĐoạn mã trên tạo ra một danh sách các khung hình 3D.\n\nĐầu tiên, ta lấy mã thông tin về khung hình đầu tiên trong cảnh (my_scene) bằng cách sử dụng khóa first_sample_token và gán cho biến first_sample_token.\n\nTiếp theo, ta khởi tạo biến token với giá trị của first_sample_token.\n\nSử dụng một vòng lặp for và tqdm, ta lặp qua một khoảng từ 0 đến nbr_samples (số lượng mẫu) trong cảnh.\n\nTrong mỗi vòng lặp, ta sử dụng mã thông tin về mẫu (sample) từ tập dữ liệu Lyft bằng cách sử dụng hàm lyftdata.get('sample', token).\n\nTa lấy mã thông tin về dữ liệu LiDAR của khung hình từ khóa data trong mẫu (sample['data']['LIDAR_TOP']).\n\nTiếp theo, ta gọi hàm draw_3d_plot(i, lidar_token) để vẽ hình ảnh 3D của dữ liệu LiDAR với chỉ số khung hình i và mã dữ liệu LiDAR lidar_token.\n\nHàm draw_3d_plot() sẽ trả về tên tệp PNG của hình ảnh 3D được lưu, và ta thêm tên tệp này vào danh sách frames bằng cách sử dụng phép gán += [filename].\n\nCuối cùng, ta cập nhật giá trị của biến token thành mã của mẫu tiếp theo bằng cách sử dụng khóa next trong mã thông tin của mẫu (sample['next']).\n\nĐoạn mã có thể được chỉnh sửa để chỉ xem một số lượng nhất định của khung hình bằng cách thêm một câu lệnh break vào cuối vòng lặp.","metadata":{}},{"cell_type":"code","source":"clip = ImageSequenceClip(frames, fps=5)\nclip.write_gif('pcl_data.gif', fps=5);","metadata":{"execution":{"iopub.status.busy":"2023-06-05T15:24:44.461870Z","iopub.execute_input":"2023-06-05T15:24:44.462475Z","iopub.status.idle":"2023-06-05T15:25:00.424385Z","shell.execute_reply.started":"2023-06-05T15:24:44.462408Z","shell.execute_reply":"2023-06-05T15:25:00.423237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\nĐoạn mã trên tạo ra một tệp GIF từ danh sách các khung hình (frames) đã tạo trước đó.\n\nĐầu tiên, ta sử dụng thư viện moviepy để tạo một đối tượng ImageSequenceClip từ danh sách các khung hình (frames) và đặt tốc độ khung hình (fps) là 5.\n\nSau đó, ta gọi phương thức write_gif trên đối tượng clip để tạo tệp GIF. Tệp GIF được đặt tên là \"pcl_data.gif\" và có tốc độ khung hình là 5.\n\nKết quả là một tệp GIF được tạo ra từ các khung hình và được lưu dưới dạng \"pcl_data.gif\".","metadata":{}},{"cell_type":"code","source":"from IPython.core.interactiveshell import InteractiveShell\nInteractiveShell.ast_node_interactivity = \"all\"\nfrom IPython import display","metadata":{"execution":{"iopub.status.busy":"2023-06-05T15:25:00.427059Z","iopub.execute_input":"2023-06-05T15:25:00.427528Z","iopub.status.idle":"2023-06-05T15:25:00.433349Z","shell.execute_reply.started":"2023-06-05T15:25:00.427447Z","shell.execute_reply":"2023-06-05T15:25:00.432234Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Đoạn mã trên là cấu hình cho IPython Shell (giao diện dòng lệnh tương tác của IPython) để hiển thị kết quả của tất cả các câu lệnh thay vì chỉ hiển thị kết quả của câu lệnh cuối cùng.\n\nCụ thể, đoạn mã sử dụng InteractiveShell từ module IPython.core.interactiveshell để cấu hình giao diện dòng lệnh. Dòng lệnh InteractiveShell.ast_node_interactivity = \"all\" cho phép hiển thị kết quả của tất cả các câu lệnh. Sau đó, module IPython.display được import để sử dụng các phương thức liên quan đến hiển thị trong IPython.\n\nCấu hình này giúp cho khi chạy các ô mã trong môi trường IPython, kết quả của mỗi câu lệnh sẽ được hiển thị ngay sau câu lệnh đó, thay vì chỉ hiển thị kết quả của câu lệnh cuối cùng. Điều này giúp dễ dàng theo dõi và xem kết quả từng bước trong quá trình thực thi mã.","metadata":{}},{"cell_type":"code","source":"with open('pcl_data.gif','rb') as f:\n    display.Image(data=f.read(), format='png')","metadata":{"execution":{"iopub.status.busy":"2023-06-05T15:25:00.435156Z","iopub.execute_input":"2023-06-05T15:25:00.435599Z","iopub.status.idle":"2023-06-05T15:25:00.741361Z","shell.execute_reply.started":"2023-06-05T15:25:00.435518Z","shell.execute_reply":"2023-06-05T15:25:00.739641Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Đoạn mã trên đọc và hiển thị một tệp GIF có tên 'pcl_data.gif' trong môi trường IPython.\n\nTrước tiên, nó mở tệp GIF bằng câu lệnh open('pcl_data.gif','rb'). Điều này mở tệp trong chế độ đọc nhị phân ('rb' - read binary), cho phép đọc dữ liệu từ tệp.\n\nSau đó, nó sử dụng display.Image từ module IPython.display để hiển thị nội dung của tệp GIF. Tham số data nhận giá trị của dữ liệu tệp GIF đã đọc (f.read()) và tham số format chỉ định định dạng của tệp (trong trường hợp này là 'png').\n\nKết quả là hình ảnh GIF được hiển thị trong môi trường IPython, cho phép bạn xem tệp GIF 'pcl_data.gif'.","metadata":{}}]}