Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rghuang Dev Branch Merge #2

Open
wants to merge 59 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
cf0a3c2
New: image_registration_engine - ransac_flow, LoFTR
jinhoyi Dec 16, 2023
2cfbd40
Frontend Update: basic file metadata, object detection, autoplay, ove…
jinhoyi Dec 21, 2023
2b2586d
added GroundingDino repo
jinhoyi Dec 21, 2023
8cca33a
git ignore update
jinhoyi Dec 21, 2023
daf84cd
Updated Instructions
jinhoyi Dec 22, 2023
51d47a8
Bug Fix; Run button deactivating issue fixed
jinhoyi Dec 22, 2023
a8d6a49
Update: align mode
jinhoyi Dec 22, 2023
ab1fd17
Minor Layout Update
jinhoyi Dec 22, 2023
ef28ac6
Bug Fix: file explorer not showing all routes
jinhoyi Dec 22, 2023
43f3478
added Metadata for delete
jinhoyi Dec 22, 2023
312c1e5
Bug Fix: Resets video selection after changing the routes
jinhoyi Dec 25, 2023
5805b6e
Published Dev
jinhoyi Jan 5, 2024
f638654
Streamlit Migration: Streamlit-resultpage v0.1.0
jinhoyi Jan 17, 2024
3a4ae44
file_UX half commit
jinhoyi Jan 25, 2024
1ded0b8
Info Remaining
jinhoyi Jan 26, 2024
0c8dce7
Modified column managing
jinhoyi Jan 26, 2024
1f0f061
working Streamlit app
jinhoyi Jan 31, 2024
b9438ae
Deep Analysis Error fixed
jinhoyi Jan 31, 2024
3f2c3df
removed image_comparison import
jinhoyi Feb 1, 2024
1714908
setup_conda updated for python3.11
jinhoyi Feb 1, 2024
6fad696
error_change
jinhoyi Feb 14, 2024
b203e43
clean up streamlit-float
jinhoyi Feb 14, 2024
ac6cc58
Added streamlit-float
jinhoyi Feb 14, 2024
e76ee8a
Merged Main
jinhoyi Feb 14, 2024
98836a4
Merge branch 'main' into dev
jinhoyi Feb 14, 2024
a990f2b
Real-time algorithm ready - Next: implement backend-driven rerun + pi…
jinhoyi Mar 5, 2024
0b702bf
Mock Real-time working - Bug: User _get_websocket_headers() returns None
jinhoyi Mar 6, 2024
a8db0da
Merged comparison frame into single element, beginning object annotat…
May 21, 2024
f79ab4a
Basic annotation tab using streamlit-image-annotation
May 21, 2024
ef2191e
Remove images for testing
May 22, 2024
285bd62
update dependencies in setup_conda
May 22, 2024
bd40c68
Update dependencies in setup_conda
May 22, 2024
763f3f1
Basic object detection with moveable bounding boxes in annotation tab
May 23, 2024
72de8e8
Simple UI for annotating, generates moveable box plots around detecte…
May 24, 2024
f1f6282
migrated annotation UI to streamlit_label_kit
May 28, 2024
14de4d0
Quetzal_realtime
jinhoyi Jun 7, 2024
ebe8363
Mask generation for change detection model
Jun 7, 2024
0abdd06
Working on segmentation annotation overlay
Jun 17, 2024
4063279
Fixing segmentation buffer bug
Jun 17, 2024
98c03ed
Initial labeling platform with detection and segmentation completed
Jun 20, 2024
5a08118
Initial labeling platform with detection and segmentation completed
rgyhuang Jun 20, 2024
77fa1e7
Merge branch 'rghuang_dev' of https://github.com/cmusatyalab/quetzal …
rgyhuang Jun 20, 2024
ad99955
Streamlit upgrade, fragment scoped refresh for annotation windows
rgyhuang Jul 29, 2024
81cc1d9
Code cleanup, label list fix
rgyhuang Jul 30, 2024
9b7e705
Setup update, code cleanup
rgyhuang Jul 31, 2024
2ddee42
Code cleanup
rgyhuang Jul 31, 2024
495d817
Remove test files
rgyhuang Jul 31, 2024
1d4867c
Remove unused imports and dead code
rgyhuang Jul 31, 2024
62c8ccc
Update readme
rgyhuang Aug 1, 2024
b2117e1
Update readme
rgyhuang Aug 1, 2024
cb6a100
Update readme
rgyhuang Aug 1, 2024
1834f97
Update readme
rgyhuang Aug 1, 2024
1cd4725
Update readme
rgyhuang Aug 1, 2024
9d0257e
Update README.md
rgyhuang Aug 1, 2024
8a696b4
Update README.md
rgyhuang Aug 1, 2024
b38005c
Remove data.json
rgyhuang Aug 1, 2024
d78428f
Merge branch 'main' into rghuang_dev
rgyhuang Aug 1, 2024
72ba9a7
Update readme
rgyhuang Aug 1, 2024
e1c471a
Merge branch 'rghuang_dev' of https://github.com/cmusatyalab/quetzal …
rgyhuang Aug 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
**/__pycache__/

compare_aligned_idx_copy.py
*.ipynb
*.pkl
quetzal/external/RANSAC_flow/model/pretrained/
# src/external/RANSAC_flow/model/pretrained/
weights/
Expand All @@ -12,4 +14,14 @@ gradio_UX.py
# Builds
**/*.egg-info/
**/build/
**/dist/
**/dist/

# dataset
**/data/
data.tar

# annotations
**/annotations/

# secrets
.env
48 changes: 33 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,24 @@

Quetzal provides automatic frame alignment between two drone footages taken along similar routes.

Quetzal offers automated frame alignment for drone footage captured along similar routes. The Quetzal app features a file-system GUI designed for organizing and sharing various projects and videos, enabling users to compare two videos from the database. Additionally, it incorporates zero-shot object detection ([GroundingSAM](https://github.com/IDEA-Research/Grounded-Segment-Anything)), allowing users to search for objects within video frames based on text prompts provided.
Quetzal offers automated frame alignment for drone footage captured along similar routes. The Quetzal app features a file-system GUI designed for organizing and sharing various projects and videos, enabling users to compare two videos from the database. Additionally, it incorporates zero-shot object detection ([GroundingSAM](https://github.com/IDEA-Research/Grounded-Segment-Anything)), allowing users to search for objects within video frames based on text prompts provided and annotate frames with interesting observations or changes.


**File-explorer view**

<img src="./demo/demo_file_explorer.png" height="400" />
<img src="./demo/demo_file_explorer.png" height="400" width="650" />

**Video Comparison View**

<img src="./demo/demo_frame_alignment.png" height="400" />
<img src="./demo/demo_frame_alignment.png" height="400" width="650" />

**Object Detection View**

<img src="./demo/demo_object_detection.png" height="400" />
<img src="./demo/demo_object_detection.png" height="400" width="650"/>

**Object Annotation View**

<img src="./demo/demo_object_annotation.png" height="400" width="650">


**Future Plans:** Support change detection between two drone footages.
Expand Down Expand Up @@ -77,15 +80,15 @@ run ./mkdocs.sh on root dir
To run the Quetzal app on a GPU server, use the following command:

```bash
python3 -m quetzal_app -l "127.0.0.1" -p PORT_NUM --dataset-root /data/root --metadata-root /meta_data/root --cuda --cuda-device 0 -u USER_NAME
python3 -m quetzal_app -l "127.0.0.1" -p PORT_NUM --dataset-root ./data/root --metadata-root ./meta_data/root --cuda --cuda-device 0 -u USER_NAME
```

### CPU Only:

For systems without a GPU, execute the following command:

```bash
python3 -m quetzal_app -l "127.0.0.1" -p PORT_NUM --dataset-root /data/root --metadata-root /meta_data/root -u USER_NAME
python3 -m quetzal_app -l "127.0.0.1" -p PORT_NUM --dataset-root ./data/root --metadata-root ./meta_data/root -u USER_NAME
```

The default user is "default_user".
Expand All @@ -94,24 +97,24 @@ The default user is "default_user".
Quetzal provides a CLI for setting up the dataset directory. You can use the following commands to initialize the directory, add a user, or import/convert an existing directory to create a Quetzal-compatible meta-dataset directory.

### Initialize Dataset and Meta-dataset Directories
To initialize the dataset folder at "/data/root" and meta-dataset at "/meta_data/root":
To initialize the dataset folder at "./data/root" and meta-dataset at "./meta_data/root":

```bash
python3 -m quetzal init -d /data/root -m /meta_data/root
python3 -m quetzal init -d ./data/root -m ./meta_data/root
```

### Add a User Directory for the Dataset
To add a user directory for the dataset at "/data/root":
To add a user directory for the dataset at "./data/root":

```bash
python3 -m quetzal user -d /data/root -m /meta_data/root -u USER_NAME
python3 -m quetzal user -d ./data/root -m ./meta_data/root -u USER_NAME
```

### Import Dataset and Create Meta-dataset
To import a dataset from "/data/root" and create a meta-dataset at "/meta_data/root":
To import a dataset from "./data/root" and create a meta-dataset at "./meta_data/root":

```bash
python3 -m quetzal import -d /data/root -m /meta_data/root
python3 -m quetzal import -d ./data/root -m ./meta_data/root
```

The default root dataset directory is "./data/home/root," and the default meta-dataset directory is "./data/meta_data/root."
Expand Down Expand Up @@ -183,14 +186,29 @@ The File-system GUI of Quetzal mirrors the user-friendly design found in many po

To enter a directory you've previously selected, simply click on it again. To navigate back or to a different parent directory, use the breadcrumb navigation at the top.

For video files, the information section includes an "Analyze" option. This feature allows you to register the video for comparison. Once analyzed, you have the choice to mark the video as a "Use as Query" or "Use as Database" for comparison purposes. After selecting one video for each category, proceed by clicking "RUN COMPARISON" on the left side of the screen to move to the comparison page
For video files, the information section includes an "Analyze" option. This feature allows you to register the video for comparison. Once analyzed, you have the choice to mark the video as a "Use as Query" or "Use as Database" for comparison purposes. After selecting one video for each category, proceed by clicking "RUN COMPARISON" on the left side of the screen to move to the comparison page. To run the real-time matching algorithm, fill out the information to your redis server in `./quetzal_app/page/page_video_comparison_stream.py` (line 485), select your query and database videos, and click "STREAM MATCHING".

The comparison page showcases the frame from the query video on the left and the aligned frame from the database video on the right, arranged side by side. Additionally, for the image on the right, a slider is provided, enabling you to overlay and compare the two frames directly.

To delve into zero-shot object detection on the current frame, click on the "object-detection" tab.
To delve into zero-shot object detection on the current frame, click on the "object-detection" tab.

To annotate images, click on the "object-annotation" tab. Here, users can use zero-shot object detection to generate editable bounding boxes. After editing the bounding boxes, users can also segment the image. Saving the annotation creates a .json file with the following format:
```json
{
"image_query": "original query image (base64)",
"image_db": "original database image (base64)",
"bboxes_query": "bounding box annotations for query image",
"bboxes_db": "bounding box annotations for database image",
"mask_query": "2D list with query masks",
"mask_db": "2D list with database masks",
"annotated_query": "query image with masks and bounding boxes printed onto the image",
"annotated_db": "database image with masks and bounding boxes printed onto the image",
"mask_combined": "2D array with both query and database masks combined",
}
```

## Developing Extensions
To ensure backend algorithms are compatible with Quetzal_app, modifications to files/directories should utilize `quetzal.dtos.dtos.QuetzalFile` and `quetzal.dtos.video.Video` objects. For guidance on generating cached/meta data associated with specific files, please refer to the modules `quetzal.engines.vpr_engine.anyloc_engine` and `quetzal.engines.image_registration_engine.loftr_engine`. These references will provide insights into how and where to manage cached/meta data effectively.


To expand the selection of Object Detection models, please refere to the `quetzal.engines.detection_engine.grounding_sam_engine` and its implementation within `quetzal_app.page.video_comparison_controller`. To integrate your custom object detection model, follow the structure of the abstract class defined in `quetzal.engines.engine`. Then, register your model by adding it to the `detector_dict` within `quetzal_app.page.video_comparison_controller`.
To expand the selection of Object Detection models, please refere to the `quetzal.engines.detection_engine.grounding_sam_engine` and its implementation within `quetzal_app.page.video_comparison_controller`. To integrate your custom object detection model, follow the structure of the abstract class defined in `quetzal.engines.engine`. Then, register your model by adding it to the `detector_dict` within `quetzal_app.page.video_comparison_controller`.
127 changes: 127 additions & 0 deletions compute_vlad.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
from quetzal.dtos.video import *
import logging
from quetzal.engines.vpr_engine.anyloc_engine import AnyLocEngine
import torch
import sys

# Compute_vlad - For "Detection of Tunable and Explainable Salient Changes".
logging.basicConfig()
logger = logging.getLogger("compute_vlad")
logger.setLevel(logging.DEBUG)

import argparse

dataset_layout_help = """
Your dataset directory will be structured as following
Place your desired video files in dataset_root/route_name/raw_videos/

Dataset structure:
dataset_root/
|
├── route_name/
| ├── raw_video/
| | ├── video_name.mp4
| | └── ...
| |
| ├── database/
| | ├── video_name/
| | | ├── frames_{fps}_{resolution}/
| | | | ├── frame_%05d.jpg
| | | | └── ...
| | | └── ...
| | └── ...
| |
| ├── query/
| | ├── video_name/
| | | ├── frames_{fps}_{resolution}/
| | | | ├── frame_%05d.jpg
| | | | └── ...
| | | └── ...
| | └── ...
| └── ...
└── ...
"""

def generate_VLAD(database_video: Video, query_video: Video, torch_device):
"""
Generates VLAD descriptors for the given database and query videos.

Args:
database_video (Video): The video object representing the database video.
query_video (Video): The video object representing the query video.
torch_device (torch.device): The PyTorch device to use for computations.

Returns:
Tuple[np.ndarray, np.ndarray]: A tuple containing the VLAD descriptors for the database and query videos.
"""

logger.info("Loading Videos")
anylocEngine = AnyLocEngine(
database_video=database_video,
query_video=query_video,
device=torch_device,
mode="lazy",
)

db_vlad = anylocEngine.get_database_vlad()
query_vlad = anylocEngine.get_query_vlad()
del anylocEngine

return db_vlad, query_vlad


def main():
parser = argparse.ArgumentParser(
formatter_class=argparse.RawTextHelpFormatter,
description="This program computes ",
epilog=dataset_layout_help,
)
# ... add arguments to parser ...
parser.add_argument(
"--dataset-root", default="../data", help="Root directory of datasets"
)
parser.add_argument("--route-name", required=True, help="Name of the route")
parser.add_argument("--database-video", help="Database video file name")
parser.add_argument("--query-video", help="Query video file name")
parser.add_argument(
"--cuda", action="store_true", help="Enable cuda", default=False
)
parser.add_argument("--cuda_device", help="Select cuda device", default=0, type=int)

args = parser.parse_args()

if not (args.database_video or args.query_video):
parser.print_usage()
print("Error: Either --database-video or --query-video must be provided.")
sys.exit(1)

device = torch.device("cpu")
available_gpus = torch.cuda.device_count()
if args.cuda and available_gpus > 0:
cuda_device = args.cuda_device if args.cuda_device < available_gpus else 0
device = torch.device("cuda:" + str(cuda_device))

## Initialize System

# Load Video frames
logger.info("Loading Videos")
database_video, query_video = None, None

if args.database_video:
database_video = DatabaseVideo(
datasets_dir=args.dataset_root,
route_name=args.route_name,
video_name=args.database_video,
)
if args.query_video:
query_video = QueryVideo(
datasets_dir=args.dataset_root,
route_name=args.route_name,
video_name=args.query_video,
)

generate_VLAD(database_video, query_video, device)


if __name__ == "__main__":
main()
Binary file modified demo/demo_file_explorer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified demo/demo_frame_alignment.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added demo/demo_object_annotation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified demo/demo_object_detection.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading