Skip to content

patches.Scatter() and patches.Plot() should be added. #29318

Closed

Description

@hyperkai

Problem

Only using patches.Rectangle() of plt.subplots() works properly as shown below:

from torchvision.datasets import CelebA

my_data = CelebA(
    root="data",
    split="all",
    target_type=["bbox", "landmarks"]
)

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

fig, axes = plt.subplots(nrows=2, ncols=5, figsize=(12, 6))
for (im, ((x, y, w, h), lm)), axis in zip(my_data, axes.ravel()):
    axis.imshow(X=im)
    rect = Rectangle(xy=(x, y), width=w, height=h, linewidth=3, edgecolor='r', facecolor='none', clip_on=True) # Here
    axis.add_patch(p=rect)                                                                                     # Here

Screenshot 2024-12-16 012242

And only using axes.Axes.scatter() of plt.subplots() works properly as shown below:

from torchvision.datasets import CelebA
import torchvision

my_data = CelebA(
    root="data",
    split="all",
    target_type=["bbox", "landmarks"]
)

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from matplotlib.patches import Circle

fig, axes = plt.subplots(nrows=2, ncols=5, figsize=(12, 6))
for (im, ((x, y, w, h), lm)), axis in zip(my_data, axes.ravel()):
    axis.imshow(X=im)

    for px, py in lm.split(2):                # Here
        axis.scatter(x=px, y=py, c='#1f77b4') # Here

Screenshot 2024-12-16 020807

And only using axes.Axes.plot() of plt.subplots() works properly as shown below:

from torchvision.datasets import CelebA
import torchvision

my_data = CelebA(
    root="data",
    split="all",
    target_type=["bbox", "landmarks"]
)

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from matplotlib.patches import Circle

fig, axes = plt.subplots(nrows=2, ncols=5, figsize=(12, 6))
for (im, ((x, y, w, h), lm)), axis in zip(my_data, axes.ravel()):
    axis.imshow(X=im)

    px = []                    # Here
    py = []                    # Here
    for j, v in enumerate(lm): # Here
        if j%2 == 0:           # Here
            px.append(v)       # Here
        else:                  # Here
            py.append(v)       # Here
    axis.plot(px, py)          # Here

Screenshot 2024-12-16 021239

But using patches.Rectangle() of plt.subplots() with axes.Axes.scatter() of plt.subplots() doesn't work properly as shown below:

from torchvision.datasets import CelebA

my_data = CelebA(
    root="data",
    split="all",
    target_type=["bbox", "landmarks"]
)

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

fig, axes = plt.subplots(nrows=2, ncols=5, figsize=(12, 6))
for (im, ((x, y, w, h), lm)), axis in zip(my_data, axes.ravel()):
    axis.imshow(X=im)
    rect = Rectangle(xy=(x, y), width=w, height=h, linewidth=3, edgecolor='r', facecolor='none', clip_on=True) # Here
    axis.add_patch(p=rect)                                                                                     # Here

    for px, py in lm.split(2):                # Here
        axis.scatter(x=px, y=py, c='#1f77b4') # Here

Screenshot 2024-12-16 012506

And using patches.Rectangle() of plt.subplots() with axes.Axes.plot() of plt.subplots() doesn't work properly as shown below:

from torchvision.datasets import CelebA

my_data = CelebA(
    root="data",
    split="all",
    target_type=["bbox", "landmarks"]
)

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

fig, axes = plt.subplots(nrows=2, ncols=5, figsize=(12, 6))
for (im, ((x, y, w, h), lm)), axis in zip(my_data, axes.ravel()):
    axis.imshow(X=im)
    rect = Rectangle(xy=(x, y), width=w, height=h, linewidth=3, edgecolor='r', facecolor='none', clip_on=True) # Here
    axis.add_patch(p=rect)                                                                                     # Here

    px = []                    # Here
    py = []                    # Here
    for j, v in enumerate(lm): # Here
        if j%2 == 0:           # Here
            px.append(v)       # Here
        else:                  # Here
            py.append(v)       # Here
    axis.plot(px, py)          # Here

Screenshot 2024-12-16 013942

So instead, I used patches.Rectangle() of plt.subplots() with patches.Circle() of plt.subplots(), then they properly work as shown below:

from torchvision.datasets import CelebA

my_data = CelebA(
    root="data",
    split="all",
    target_type=["bbox", "landmarks"]
)

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from matplotlib.patches import Circle

fig, axes = plt.subplots(nrows=2, ncols=5, figsize=(12, 6))
for (im, ((x, y, w, h), lm)), axis in zip(my_data, axes.ravel()):
    axis.imshow(X=im)
    rect = Rectangle(xy=(x, y), width=w, height=h, linewidth=3, edgecolor='r', facecolor='none', clip_on=True) # Here
    axis.add_patch(p=rect)                                                                                     # Here

    for px, py in lm.split(2):                # Here
        axis.add_patch(p=Circle(xy=(px, py))) # Here

Screenshot 2024-12-16 014626

Proposed solution

So, it seems like matplotlib.patches works with matplotlib.patches so patches.Scatter() and patches.Plot() should be added.

Activity

  1. jklymak commented on Dec 15, 2024

    @jklymak
    Member

    They are all working the same, just scatter is calling autolim, and add_patch is not.

  2. timhoffm commented on Dec 17, 2024

    @timhoffm
    Member

    What is happening:

    • add_patch() is a lower-level function and updates the data limits (Axes.dataLim) to include the Patch, but doesn't touch the view limits (Axes.viewLim).
    • scatter() is a high-level function that additionally updates the view limits based on the data limits (essentially through a lazy autoscale_view()), which then picks up the rectangle limits as well.

    If you want to have limits exactly on the image, no matter what you plot afterwards you should call ax.autoscale(False) after ax.imshow().

  3. timhoffm commented on Dec 17, 2024

    @timhoffm
    Member

    I'm closing as the solution for the present case is to deactivate autoscaling.

    Independent of this, there are some ideas how to change/improve autoscaling. These are independently tracked, e.g. in

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions