Spaces:
Running
Running
update: re-match using warped pair
Browse files- common/app_class.py +47 -23
- common/utils.py +28 -8
common/app_class.py
CHANGED
|
@@ -10,6 +10,7 @@ from common.utils import (
|
|
| 10 |
get_matcher_zoo,
|
| 11 |
run_matching,
|
| 12 |
run_ransac,
|
|
|
|
| 13 |
gen_examples,
|
| 14 |
GRADIO_VERSION,
|
| 15 |
ROOT,
|
|
@@ -212,32 +213,44 @@ class ImageMatchingApp:
|
|
| 212 |
# Add some examples
|
| 213 |
with gr.Row():
|
| 214 |
# Example inputs
|
| 215 |
-
gr.
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
|
|
|
|
|
|
|
|
|
| 226 |
with gr.Accordion("Supported Algorithms", open=False):
|
| 227 |
# add a table of supported algorithms
|
| 228 |
self.display_supported_algorithms()
|
| 229 |
|
| 230 |
with gr.Column():
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
)
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 241 |
with gr.Accordion(
|
| 242 |
"Open for More: Matches Statistics", open=False
|
| 243 |
):
|
|
@@ -247,11 +260,16 @@ class ImageMatchingApp:
|
|
| 247 |
matcher_info = gr.JSON(label="Match info")
|
| 248 |
|
| 249 |
with gr.Accordion(
|
| 250 |
-
"Open for More: Warped Image", open=
|
| 251 |
):
|
| 252 |
output_wrapped = gr.Image(
|
| 253 |
label="Wrapped Pair", type="numpy"
|
| 254 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 255 |
with gr.Accordion(
|
| 256 |
"Open for More: Geometry info", open=False
|
| 257 |
):
|
|
@@ -286,7 +304,6 @@ class ImageMatchingApp:
|
|
| 286 |
button_run.click(
|
| 287 |
fn=run_matching, inputs=inputs, outputs=outputs
|
| 288 |
)
|
| 289 |
-
|
| 290 |
# Reset images
|
| 291 |
reset_outputs = [
|
| 292 |
input_image0,
|
|
@@ -335,6 +352,13 @@ class ImageMatchingApp:
|
|
| 335 |
],
|
| 336 |
)
|
| 337 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 338 |
# estimate geo
|
| 339 |
choice_geometry_type.change(
|
| 340 |
fn=generate_warp_images,
|
|
|
|
| 10 |
get_matcher_zoo,
|
| 11 |
run_matching,
|
| 12 |
run_ransac,
|
| 13 |
+
send_to_match,
|
| 14 |
gen_examples,
|
| 15 |
GRADIO_VERSION,
|
| 16 |
ROOT,
|
|
|
|
| 213 |
# Add some examples
|
| 214 |
with gr.Row():
|
| 215 |
# Example inputs
|
| 216 |
+
with gr.Accordion(
|
| 217 |
+
"Open for More: Examples", open=True
|
| 218 |
+
):
|
| 219 |
+
gr.Examples(
|
| 220 |
+
examples=gen_examples(),
|
| 221 |
+
inputs=inputs,
|
| 222 |
+
outputs=[],
|
| 223 |
+
fn=run_matching,
|
| 224 |
+
cache_examples=False,
|
| 225 |
+
label=(
|
| 226 |
+
"Examples (click one of the images below to Run"
|
| 227 |
+
" Match). Thx: WxBS"
|
| 228 |
+
),
|
| 229 |
+
)
|
| 230 |
with gr.Accordion("Supported Algorithms", open=False):
|
| 231 |
# add a table of supported algorithms
|
| 232 |
self.display_supported_algorithms()
|
| 233 |
|
| 234 |
with gr.Column():
|
| 235 |
+
with gr.Accordion(
|
| 236 |
+
"Open for More: Keypoints", open=True
|
| 237 |
+
):
|
| 238 |
+
output_keypoints = gr.Image(
|
| 239 |
+
label="Keypoints", type="numpy"
|
| 240 |
+
)
|
| 241 |
+
with gr.Accordion(
|
| 242 |
+
"Open for More: Raw Matches", open=False
|
| 243 |
+
):
|
| 244 |
+
output_matches_raw = gr.Image(
|
| 245 |
+
label="Raw Matches",
|
| 246 |
+
type="numpy",
|
| 247 |
+
)
|
| 248 |
+
with gr.Accordion(
|
| 249 |
+
"Open for More: RANSAC Matches", open=True
|
| 250 |
+
):
|
| 251 |
+
output_matches_ransac = gr.Image(
|
| 252 |
+
label="Ransac Matches", type="numpy"
|
| 253 |
+
)
|
| 254 |
with gr.Accordion(
|
| 255 |
"Open for More: Matches Statistics", open=False
|
| 256 |
):
|
|
|
|
| 260 |
matcher_info = gr.JSON(label="Match info")
|
| 261 |
|
| 262 |
with gr.Accordion(
|
| 263 |
+
"Open for More: Warped Image", open=True
|
| 264 |
):
|
| 265 |
output_wrapped = gr.Image(
|
| 266 |
label="Wrapped Pair", type="numpy"
|
| 267 |
)
|
| 268 |
+
# send to input
|
| 269 |
+
button_rerun = gr.Button(
|
| 270 |
+
value="Send to Input Match Pair",
|
| 271 |
+
variant="primary",
|
| 272 |
+
)
|
| 273 |
with gr.Accordion(
|
| 274 |
"Open for More: Geometry info", open=False
|
| 275 |
):
|
|
|
|
| 304 |
button_run.click(
|
| 305 |
fn=run_matching, inputs=inputs, outputs=outputs
|
| 306 |
)
|
|
|
|
| 307 |
# Reset images
|
| 308 |
reset_outputs = [
|
| 309 |
input_image0,
|
|
|
|
| 352 |
],
|
| 353 |
)
|
| 354 |
|
| 355 |
+
# send warped image to match
|
| 356 |
+
button_rerun.click(
|
| 357 |
+
fn=send_to_match,
|
| 358 |
+
inputs=[state_cache],
|
| 359 |
+
outputs=[input_image0, input_image1],
|
| 360 |
+
)
|
| 361 |
+
|
| 362 |
# estimate geo
|
| 363 |
choice_geometry_type.change(
|
| 364 |
fn=generate_warp_images,
|
common/utils.py
CHANGED
|
@@ -649,8 +649,7 @@ def wrap_images(
|
|
| 649 |
title,
|
| 650 |
dpi=300,
|
| 651 |
)
|
| 652 |
-
|
| 653 |
-
return fig2im(fig), dictionary
|
| 654 |
else:
|
| 655 |
return None, None
|
| 656 |
|
|
@@ -660,7 +659,7 @@ def generate_warp_images(
|
|
| 660 |
input_image1: np.ndarray,
|
| 661 |
matches_info: Dict[str, Any],
|
| 662 |
choice: str,
|
| 663 |
-
) -> Tuple[Optional[np.ndarray], Optional[
|
| 664 |
"""
|
| 665 |
Changes the estimate of the geometric transformation used to align the images.
|
| 666 |
|
|
@@ -671,7 +670,7 @@ def generate_warp_images(
|
|
| 671 |
choice: Type of geometric transformation to use ('Homography' or 'Fundamental') or 'No' to disable.
|
| 672 |
|
| 673 |
Returns:
|
| 674 |
-
A tuple containing the updated images and the
|
| 675 |
"""
|
| 676 |
if (
|
| 677 |
matches_info is None
|
|
@@ -682,10 +681,29 @@ def generate_warp_images(
|
|
| 682 |
geom_info = matches_info["geom_info"]
|
| 683 |
wrapped_images = None
|
| 684 |
if choice != "No":
|
| 685 |
-
|
| 686 |
input_image0, input_image1, geom_info, choice
|
| 687 |
)
|
| 688 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 689 |
else:
|
| 690 |
return None, None
|
| 691 |
|
|
@@ -745,7 +763,7 @@ def run_ransac(
|
|
| 745 |
t1 = time.time()
|
| 746 |
|
| 747 |
# compute warp images
|
| 748 |
-
output_wrapped,
|
| 749 |
state_cache["image0_orig"],
|
| 750 |
state_cache["image1_orig"],
|
| 751 |
state_cache,
|
|
@@ -754,6 +772,7 @@ def run_ransac(
|
|
| 754 |
plt.close("all")
|
| 755 |
|
| 756 |
num_matches_raw = state_cache["num_matches_raw"]
|
|
|
|
| 757 |
return (
|
| 758 |
output_matches_ransac,
|
| 759 |
{
|
|
@@ -927,7 +946,7 @@ def run_matching(
|
|
| 927 |
|
| 928 |
t1 = time.time()
|
| 929 |
# plot wrapped images
|
| 930 |
-
output_wrapped,
|
| 931 |
pred["image0_orig"],
|
| 932 |
pred["image1_orig"],
|
| 933 |
pred,
|
|
@@ -940,6 +959,7 @@ def run_matching(
|
|
| 940 |
state_cache = pred
|
| 941 |
state_cache["num_matches_raw"] = num_matches_raw
|
| 942 |
state_cache["num_matches_ransac"] = num_matches_ransac
|
|
|
|
| 943 |
return (
|
| 944 |
output_keypoints,
|
| 945 |
output_matches_raw,
|
|
|
|
| 649 |
title,
|
| 650 |
dpi=300,
|
| 651 |
)
|
| 652 |
+
return fig2im(fig), rectified_image1
|
|
|
|
| 653 |
else:
|
| 654 |
return None, None
|
| 655 |
|
|
|
|
| 659 |
input_image1: np.ndarray,
|
| 660 |
matches_info: Dict[str, Any],
|
| 661 |
choice: str,
|
| 662 |
+
) -> Tuple[Optional[np.ndarray], Optional[np.ndarray]]:
|
| 663 |
"""
|
| 664 |
Changes the estimate of the geometric transformation used to align the images.
|
| 665 |
|
|
|
|
| 670 |
choice: Type of geometric transformation to use ('Homography' or 'Fundamental') or 'No' to disable.
|
| 671 |
|
| 672 |
Returns:
|
| 673 |
+
A tuple containing the updated images and the warpped images.
|
| 674 |
"""
|
| 675 |
if (
|
| 676 |
matches_info is None
|
|
|
|
| 681 |
geom_info = matches_info["geom_info"]
|
| 682 |
wrapped_images = None
|
| 683 |
if choice != "No":
|
| 684 |
+
wrapped_image_pair, warped_image = wrap_images(
|
| 685 |
input_image0, input_image1, geom_info, choice
|
| 686 |
)
|
| 687 |
+
return wrapped_image_pair, warped_image
|
| 688 |
+
else:
|
| 689 |
+
return None, None
|
| 690 |
+
|
| 691 |
+
|
| 692 |
+
def send_to_match(state_cache: Dict[str, Any]):
|
| 693 |
+
"""
|
| 694 |
+
Send the state cache to the match function.
|
| 695 |
+
|
| 696 |
+
Args:
|
| 697 |
+
state_cache (Dict[str, Any]): Current state of the app.
|
| 698 |
+
|
| 699 |
+
Returns:
|
| 700 |
+
None
|
| 701 |
+
"""
|
| 702 |
+
if state_cache:
|
| 703 |
+
return (
|
| 704 |
+
state_cache["image0_orig"],
|
| 705 |
+
state_cache["wrapped_image"],
|
| 706 |
+
)
|
| 707 |
else:
|
| 708 |
return None, None
|
| 709 |
|
|
|
|
| 763 |
t1 = time.time()
|
| 764 |
|
| 765 |
# compute warp images
|
| 766 |
+
output_wrapped, warped_image = generate_warp_images(
|
| 767 |
state_cache["image0_orig"],
|
| 768 |
state_cache["image1_orig"],
|
| 769 |
state_cache,
|
|
|
|
| 772 |
plt.close("all")
|
| 773 |
|
| 774 |
num_matches_raw = state_cache["num_matches_raw"]
|
| 775 |
+
state_cache["wrapped_image"] = warped_image
|
| 776 |
return (
|
| 777 |
output_matches_ransac,
|
| 778 |
{
|
|
|
|
| 946 |
|
| 947 |
t1 = time.time()
|
| 948 |
# plot wrapped images
|
| 949 |
+
output_wrapped, warped_image = generate_warp_images(
|
| 950 |
pred["image0_orig"],
|
| 951 |
pred["image1_orig"],
|
| 952 |
pred,
|
|
|
|
| 959 |
state_cache = pred
|
| 960 |
state_cache["num_matches_raw"] = num_matches_raw
|
| 961 |
state_cache["num_matches_ransac"] = num_matches_ransac
|
| 962 |
+
state_cache["wrapped_image"] = warped_image
|
| 963 |
return (
|
| 964 |
output_keypoints,
|
| 965 |
output_matches_raw,
|