0

Is there any way to input a certain coordinates (x,y) to pyplot and output its filling color in return?

ex. (0,0) -> Red , (0.75,0) -> blue , (1,1) ->white

import numpy as np
import matplotlib.pyplot as plt
plt.figure(figsize=(15,15))
x,y,x2,y2=[],[],[],[]
for i in np.linspace(0,2,300):
    x.append(np.cos(np.pi*i))
    y.append(np.sin(np.pi*i))  
    x2.append(0.5*np.cos(np.pi*i))
    y2.append(0.5*np.sin(np.pi*i))

plt.fill(x,y,'b')
plt.fill(x2,y2,'r')

Color Image

allenwei
  • 1
  • 1
  • why do you want that? Is your actual plot a `plt.imshow` or a `plt.plot`? – Crawl Cycle Nov 15 '20 at 06:26
  • Hi, what I need is more like that I save it as a picture (not literally save a file), and look up its color (not via pixel location but its original coordinates). – allenwei Nov 15 '20 at 07:57
  • Please clarify: 1. How do you "save it as a picture"? 2. What is "not literally save a file"? 3. What is the "original coordinates"? 4. What are the expected input & output that you want? – Crawl Cycle Nov 15 '20 at 08:03
  • 1&2. Just like your answer does, all operation done by a canvas rather than save a file to certain path (ex: d:/123.png) – allenwei Nov 15 '20 at 08:15
  • 3&4. I would like to input its original x,y rather than pixel location (0,0) -> Red , (0.75,0) -> blue , (1,1) ->white, output would be what color it is – allenwei Nov 15 '20 at 08:17

2 Answers2

0

Here is one possible method. Let's begin with a modified code (based on yours):

# Modified code
import numpy as np
import matplotlib.pyplot as plt
from shapely.geometry import Point, Polygon  # additional code

plt.figure(figsize=(15,15))
x,y,x2,y2=[],[],[],[]
for i in np.linspace(0,2,300):
    x.append(np.cos(np.pi*i))
    y.append(np.sin(np.pi*i))  
    x2.append(0.5*np.cos(np.pi*i))
    y2.append(0.5*np.sin(np.pi*i))

# grab the fill objects for use later
# .fill return: matplotlib.patches.Polygon object
blue_pgn = plt.fill(x,y,'b')  #Plot filled polygons
red_pgn = plt.fill(x2,y2,'r')

plt.show()

It produces the same plot as your code does, but also exposes 2 useful objects, blue_pgn and red_pgn .

This is the second part:

# Create geometries from objects in the plot
blue_geom = Polygon(blue_pgn[0].get_xy())
red_geom =  Polygon(red_pgn[0].get_xy())

# create a function
def from_xy_to_color(x,y):
    point_xy = Point(x,y)
    if red_geom.contains(point_xy):
        print("xy:",x,y,", color:","Red")
    elif blue_geom.contains(point_xy):
        print("xy:",x,y,", color:","Blue")
    else:
        print("xy:",x,y,", color:","White")

# test all the points
xys = [[0,0], [.75,0], [1,1]]
for xy in xys:
    #print(xy)
    from_xy_to_color(*xy)

The output from this part:

xy: 0 0 , color: Red
xy: 0.75 0 , color: Blue
xy: 1 1 , color: White
swatchai
  • 17,400
  • 3
  • 39
  • 58
  • Hi, what I need is more like that I save it as a picture (not literally save a file), and look up its color (not via pixel location but its original coordinates). your suggestion is a good way for the example here. but I found it will be very difficult to define each Polygon if the color area is getting more complicated in the future. Do you know other method to do that? – allenwei Nov 15 '20 at 07:57
  • @allenwei Polygon objects have many useful functions/methods to manipulate itself (try run `print(dir(blue_geom))`). You can check if the geometry is valid or not. If a polygon is too weedy, you can simplify its geometry to eliminate some of its vertices and use the result in stead. You can convert geometries to `wkt` format and save them in a file for future use. If you want more details about these stuffs, please ask as a new question because this is off-topic in the scope of this question. – swatchai Nov 15 '20 at 10:42
  • @allenwei FYI. For a new user, you can't vote up my answer until you gain some reputation points. But you can mark it “accepted”, and earn "+2" reputation. https://stackoverflow.com/help/someone-answers – swatchai Nov 23 '20 at 07:25
0

result

from matplotlib.backends.backend_agg import FigureCanvasAgg
import numpy as np
import matplotlib.pyplot as plt


def circle_coords():
    t = np.linspace(0, 2, 300) * np.pi
    x = np.cos(t)
    y = np.sin(t)
    return x, y


def plot(fig):
    ax = fig.gca()
    x, y = circle_coords()
    ax.fill(x, y, 'b')
    ax.fill(x / 2, y / 2, 'r')


def capture():
    plt.Figure((4, 4), dpi=20)
    fig = plt.gcf()
    canvas = FigureCanvasAgg(fig)
    plot(fig)
    canvas.draw()
    r = canvas_to_numpy(canvas)
    plt.close()
    return r


def canvas_to_numpy(canvas):
    s, (width, height) = canvas.print_to_buffer()
    x = np.frombuffer(s, np.uint8)
    return x.reshape((height, width, 4))


def random_points(shape, n_points=4):
    height, width = shape
    x = np.random.uniform(0, width, size=n_points)
    y = np.random.uniform(0, height, size=n_points)
    return np.vstack([x, y]).T


def main():
    arr = capture()

    p = [[360, 274],
         [379, 48],
         [117, 216]]

    fig = plt.gcf()
    ax = fig.gca()

    np.set_printoptions(precision=2)
    print(p)
    for x, y in p:
        r, g, b, a = arr[y, x] / 255
        c = f"{r, g, b}"
        print(arr[y, x])
        ax.text(x, y, c)
        ax.scatter(x, y, c="yellow")
    plt.imshow(arr)
    plt.show()
    plt.close()


main()

See: Matplotlib figure to image as a numpy array

Crawl Cycle
  • 257
  • 2
  • 8
  • this answer is almost there, while the input x,y is not by the original coordinates, ex: the center point (x,y) = (0,0) rather than (320,250) – allenwei Nov 15 '20 at 08:31