pyqtgraph scatter plot in PySide2 swaps red and blue - pyside2

I'm using a PNG image as a background to a scatter plot, but the import somehow swaps red and blue. I can 'fix' it by swapping red and blue for each pixel, but that's not a proper solution. Does anyone know what goes wrong here?
See code below:
import sys
from PySide2.QtWidgets import (
QApplication, QMainWindow, QWidget, QVBoxLayout,
)
from PySide2.QtGui import (
QImage
)
import pyqtgraph as pg
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("RGB Issue")
self.setGeometry(100, 100, 600, 200)
# set up widgets
self.add_widgets()
# show widgets
self.show()
def add_widgets(self):
# create a plot window
plot = pg.plot()
# add an image
img = QImage('flowers.png')
# convert to a format imageToArray accepts
img = img.convertToFormat(QImage.Format_ARGB32_Premultiplied)
img_array = pg.imageToArray(img, copy=True)
# ==> uncomment next line to swap red and blue
# img_array = self.swap_red_and_blue(img_array)
img_item = pg.ImageItem(img_array)
# push image back so it ends up behind the spots in the plot
img_item.setZValue(-100)
plot.addItem(img_item)
# create a layout for our widget
layout = QVBoxLayout()
# our central widget
widget = QWidget()
# set widget layout
widget.setLayout(layout)
layout.addWidget(plot)
self.setCentralWidget(widget)
def swap_red_and_blue(self, img_array):
# swap red and blue for each pixel
for r in img_array:
for c in r:
c0old = c[0] # get red value
c1old = c[1] # get green value
c2old = c[2] # get blue value
c[0] = c2old # replace red with blue
c[1] = c1old # keep green
c[2] = c0old # replace blue with red
# c[3] = 255 # set alpha to opaque
return img_array
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
This is the original image:
This is the output I get:
I get the correct output if I call method swap_red_and_blue for each pixel in the code above.

Related

Problem with images overlapping in pygame

Im having problems with blitting images to rect objects in pygame. i have a background image blitted to my main pygame window, and also an image blitted to a rect object on the screen which moves. the problem i am having is the rect object is overlapping my background image when its moving around. i was looking to only be able to see the green helicopter shape and not the black outline around it. sorry if i havent explained this very well. will try to include all files im using.
Thanks for any help
import pygame as pg
import random as r
import time
pg.init()
MAX_X = 1190
MAX_Y = 590
MIN_X = 10
MIN_Y = 10
SIZE = 100
SPEED = 1
COLOR = (0,255,0)
move_amount = 0
wn = pg.display.set_mode((1200, 600))
BG_IMG = pg.image.load('bg.png').convert()
BG_IMG = pg.transform.scale(BG_IMG, (1200, 600))
class Wall (pg.Rect):
def __init__(self, posX, posY):
self.xcor = posX
self.ycor = posY
self.rect = None
class Heli (pg.Rect):
def __init__(self, posX, posY):
self.image = pg.image.load('art.png').convert()
self.rect = self.image.get_rect()
self.xcor = posX
self.ycor = posY
# top and bottom constant walls
TOP = pg.Rect(MIN_X, MIN_Y, MAX_X, 3)
BOTTOM = pg.Rect(MIN_X, MAX_Y, MAX_X, 3)
heli = Heli(MIN_X, MAX_Y //2)
# keep moving walls in a list
moving_walls = [Wall(MAX_X, r.randint((MIN_Y + 10), (MAX_Y - 10)))]
# main loop
while True:
# fill screen
wn.fill('black')
# editing objects to move
# blitting must happen before everything else
pg.draw.rect(wn,COLOR, heli.rect)
wn.blit(BG_IMG, (0,0))
wn.blit(heli.image, heli.rect)
heli.rect.y += move_amount
heli.rect.y += 1
# use a variable to control how much movement is happening
# movement happens continuosly
# if key down it oves if key up it doesnt
for wall in moving_walls :
wall.rect = pg.Rect(wall.xcor, wall.ycor, 3, SIZE)
pg.draw.rect(wn, COLOR, wall.rect)
wall.xcor -= SPEED
if wall.xcor < MIN_X + 10:
wall.xcor = MAX_X
wall.ycor = r.randint((MIN_Y), (MAX_Y - SIZE))
# drawing all objects back to the screen
pg.draw.rect(wn, COLOR, TOP)
pg.draw.rect(wn, COLOR, BOTTOM)
# update window
pg.display.update()
# event handling
for ev in pg.event.get():
if ev.type == pg.KEYDOWN:
if ev.key == pg.K_UP:
move_amount = -3
if ev.type == pg.KEYUP:
move_amount = 0
if ev.type == pg.QUIT:
pg.quit()
time.sleep(0.01)
You discard the transparency information of the image. You have to use convert_alpha instead of convert:
self.image = pg.image.load('art.png').convert()
self.image = pg.image.load('art.png').convert_alpha()
The pygame documentation notes that:
The returned Surface will contain the same color format, colorkey and alpha transparency as the file it came from. You will often want to call convert() with no arguments, to create a copy that will draw more quickly on the screen.
For alpha transparency, like in .png images, use the convert_alpha() method after loading so that the image has per pixel transparency.
See also How can I make an Image with a transparent Backround in Pygame?

How to Plot YCBCR color space image with matplotlib?

This is my code it shows all color spaces except YCBCR ,,
Notation:ConvertLayer converts color space of image
fig=plt.figure(figsize=(9, 9))
for images, labels in train_ds.take(1):
for i in range(16):
plt.subplot(5, 5, i + 1)
color_space = COLOR_SPACES[i%5]
image = tf.expand_dims(images[i//5] ,axis=0)
image = augmentation(NormalLayer(color_space)(tf.cast(image,tf.float32)))
if color_space=="YCBCR":
image = tf.cast(image, tf.uint8)
image = ConvertLayer(color_space)(image)
#image = tf.cast(image * 255.0, tf.uint8)
lbl = "{}({})".format(class_names[labels[i//4].numpy().argmax()] , color_space )
plt.imshow(tf.squeeze(image))
plt.title(lbl)
plt.axis("off")
break
I need to visualize it just in matplotlib.
With the following code I was able to visualize the image in matplotlib.
import matplotlib.pyplot as plt
import numpy as np
x=plt.imread("/content/car.jpeg")
y=rgb2ycbcr(x)
fig = plt.figure(figsize=(10, 7))
rows = 1
columns = 2
fig.add_subplot(rows, columns, 1)
plt.imshow(x)
plt.axis('off')
plt.title("RGB")
fig.add_subplot(rows, columns, 2)
plt.imshow(y)
plt.axis('off')
plt.title("YCBCR")
def rgb2ycbcr(im):
xform = np.array([[.299, .587, .114], [-.1687, -.3313, .5], [.5, -.4187, -.0813]])
ycbcr = im.dot(xform.T)
ycbcr[:,:,[1,2]] += 128
return np.uint8(ycbcr)
Output:

Feathered edges on image with Pillow

I'm trying to figure out how to feather the edges of an image using Pillow with Python.
I need something like this cute cat (ignore the visible edges):
I tried im.filter(ImageFilter.BLUR) but is not what I'm looking for.
Have a look at this example:
from PIL import Image
from PIL import ImageFilter
RADIUS = 10
# Open an image
im = Image.open(INPUT_IMAGE_FILENAME)
# Paste image on white background
diam = 2*RADIUS
back = Image.new('RGB', (im.size[0]+diam, im.size[1]+diam), (255,255,255))
back.paste(im, (RADIUS, RADIUS))
# Create blur mask
mask = Image.new('L', (im.size[0]+diam, im.size[1]+diam), 255)
blck = Image.new('L', (im.size[0]-diam, im.size[1]-diam), 0)
mask.paste(blck, (diam, diam))
# Blur image and paste blurred edge according to mask
blur = back.filter(ImageFilter.GaussianBlur(RADIUS/2))
back.paste(blur, mask=mask)
back.save(OUTPUT_IMAGE_FILENAME)
Original image (author - Irene Mei):
Pasted on white background:
Blur region (paste mask):
Result:
Providing modified solution with gradient paste mask (as requested by #Crickets).
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFilter
RADIUS = 10
# Open an image
im = Image.open(INPUT_IMAGE_FILENAME)
# Paste image on white background
diam = 2*RADIUS
back = Image.new('RGB', (im.size[0]+diam, im.size[1]+diam), (255,255,255))
back.paste(im, (RADIUS, RADIUS))
# Create paste mask
mask = Image.new('L', back.size, 0)
draw = ImageDraw.Draw(mask)
x0, y0 = 0, 0
x1, y1 = back.size
for d in range(diam+RADIUS):
x1, y1 = x1-1, y1-1
alpha = 255 if d<RADIUS else int(255*(diam+RADIUS-d)/diam)
draw.rectangle([x0, y0, x1, y1], outline=alpha)
x0, y0 = x0+1, y0+1
# Blur image and paste blurred edge according to mask
blur = back.filter(ImageFilter.GaussianBlur(RADIUS/2))
back.paste(blur, mask=mask)
back.save(OUTPUT_IMAGE_FILENAME)
Paste mask:
Result:

Image segmentation based on mouse click

Using python framework we are able to create image segments as shown in attachment. Now, based on the mouse click in the image segment we need to highlight the segment with specific color.
Based on the mouse click I am able to get x/y coordinates of the specific location. Please suggest me how can I check on which image segment the coordinates belongs to?
The following is the code snippet:
from skimage.segmentation import felzenszwalb, slic,quickshift
from skimage.segmentation import mark_boundaries
from skimage.segmentation import find_boundaries
from skimage.util import img_as_float
from skimage import io
import matplotlib.pyplot as plt
from skimage import measure
from skimage import restoration
from skimage import img_as_float
import numpy as np
coords = []
def find_nearest(array,value):
idx = (np.abs(array-value)).argmin()
return array[idx]
def onclick(event):
global ix, iy
ix, iy = event.xdata, event.ydata
print ('ix ',ix)
print ("iy ",iy)
color = np.float64([1,0,1]) # red color
image[segments == 14] = color
mark_boundaries(image, segments)
ax.imshow(mark_boundaries(image, segments))
coords.append((ix, iy))
return
image=img_as_float(io.imread("amazon.jpg"))
segments = quickshift(image, ratio=1.0, kernel_size=20, max_dist=10,
return_tree=False, sigma=0, convert2lab=True, random_seed=42)
fig = plt.figure("Superpixels -- %d segments" % (500))
ax = fig.add_subplot(1, 1, 1)
fig,ax = plt.subplots()
color = np.float64([1,0,0])
image[segments == 14] = color # desired segment to be colored
fig.canvas.mpl_connect('button_press_event', onclick)
ax.imshow(mark_boundaries(image, segments))
plt.axis("off")
plt.show()
According to the documentation, quickshift returns an integer mask indicating segment labels. If you know what pixel the user clicked on, you can check the value of that pixel in your variable segments to get the segment number.
In you click handler, you can use
clicked_segment = segments[event.xdata, event.ydata]

Animate like Google Finance charts in Matplotlib?

I just started toying around with Matplotlib's Animation capabilities in order to produce a Google Finance looking chart.
I combined two examples I found on the project website (Draggable rectangle exercise, api example code: date_demo.py) and tweaked them a bit to come up with the code listed at the bottom.
While it doesn't look too bad, I would like the top chart (master) update dynamically as the bottom chart (slave) selection is moved around, and not only when the bottom selection is released. How can I do this? I tried to move the self.rect.figure.canvas.draw() bit to the on_motion method, but it seems to interfere with the blit stuff as the bottom selection won't render properly.
So I would assume the solution would be to do the intelligent animation for the bottom chart, i.e., the blit-ing bit, while the top chart is just re-drawn altogether. The issue is that the only way I can redraw anything is through the re-drawing the whole canvas, and this would include the bottom chart. I did find the draw() method for matplotlib.axes, but I can't get it to work. As I said above, preferably I would like to just re-draw the top chart while the bottom one is blit-ed the clever way. Does anyone know how to do this?
Here is my code so far. Please excuse the code, it's a bit untidy.
import datetime
import numpy as np
import sys
import time
import wx
import matplotlib
from matplotlib.figure import Figure
import matplotlib.dates as mdates
import matplotlib.ticker as mtickers
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import matplotlib.patches as mpatches
class DraggableRectangle:
lock = None
def __init__(self, rect, master, xMin, xMax):
self.rect = rect
self.press = None
self.background = None
self.xMax = xMax
self.xMin = xMin
self.master = master
def connect(self):
self.cidpress = self.rect.figure.canvas.mpl_connect('button_press_event', self.on_press)
self.cidrelease = self.rect.figure.canvas.mpl_connect('button_release_event', self.on_release)
self.cidmotion = self.rect.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)
def on_press(self, event):
if event.inaxes != self.rect.axes: return
if DraggableRectangle.lock is not None: return
contains, attrd = self.rect.contains(event)
if not contains: return
x0, y0 = self.rect.xy
self.press = x0, y0, event.xdata, event.ydata
DraggableRectangle.lock = self
canvas = self.rect.figure.canvas
axes = self.rect.axes
self.rect.set_animated(True)
canvas.draw()
self.background = canvas.copy_from_bbox(self.rect.axes.bbox)
axes.draw_artist(self.rect)
canvas.blit(axes.bbox)
def on_motion(self, event):
if DraggableRectangle.lock is not self: return
if event.inaxes != self.rect.axes: return
x0, y0, xpress, ypress = self.press
dx = event.xdata - xpress
dy = 0
if x0+dx > self.xMax:
self.rect.set_x(self.xMax)
elif x0+dx < self.xMin:
self.rect.set_x(self.xMin)
else:
self.rect.set_x(x0+dx)
self.rect.set_y(y0+dy)
canvas = self.rect.figure.canvas
axes = self.rect.axes
canvas.restore_region(self.background)
self.master.set_xlim(self.rect.get_x(), self.rect.get_x() + 92)
axes.draw_artist(self.rect)
canvas.blit(axes.bbox)
def on_release(self, event):
if DraggableRectangle.lock is not self: return
self.press = None
DraggableRectangle.lock = None
self.rect.set_animated(False)
self.background = None
self.rect.figure.canvas.draw()
def disconnect(self):
self.rect.figure.canvas.mpl_disconnect(self.cidpress)
self.rect.figure.canvas.mpl_disconnect(self.cidrelease)
self.rect.figure.canvas.mpl_disconnect(self.cidmotion)
class MplCanvasFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, title='First Chart', size=(800, 700))
datafile = matplotlib.get_example_data('goog.npy')
r = np.load(datafile).view(np.recarray)
datesFloat = matplotlib.dates.date2num(r.date)
figure = Figure()
xMaxDatetime = r.date[len(r.date)-1]
xMinDatetime = r.date[0]
xMaxFloat = datesFloat[len(datesFloat)-1]
xMinFloat = datesFloat[0]
yMin = min(r.adj_close) // 5 * 5
yMax = (1 + max(r.adj_close) // 5) * 5
master = figure.add_subplot(211)
master.plot(datesFloat, r.adj_close)
master.xaxis.set_minor_locator(mdates.MonthLocator())
master.xaxis.set_major_locator(mdates.MonthLocator(bymonth=(1,4,7,10)))
master.xaxis.set_major_formatter(mdates.DateFormatter('%b-%y'))
master.set_xlim(datesFloat[120], datesFloat[120]+92)
master.yaxis.set_minor_locator(mtickers.MultipleLocator(50))
master.yaxis.set_major_locator(mtickers.MultipleLocator(100))
master.set_ylim(yMin, yMax)
master.set_position([0.05,0.20,0.92,0.75])
master.xaxis.grid(True, which='minor')
master.yaxis.grid(True, which='minor')
slave = figure.add_subplot(212, yticks=[])
slave.plot(datesFloat, r.adj_close)
slave.xaxis.set_minor_locator(mdates.MonthLocator())
slave.xaxis.set_major_locator(mdates.YearLocator())
slave.xaxis.set_major_formatter(mdates.DateFormatter('%b-%y'))
slave.set_xlim(xMinDatetime, xMaxDatetime)
slave.set_ylim(yMin, yMax)
slave.set_position([0.05,0.05,0.92,0.10])
rectangle = mpatches.Rectangle((datesFloat[120], yMin), 92, yMax-yMin, facecolor='yellow', alpha = 0.4)
slave.add_patch(rectangle)
canvas = FigureCanvas(self, -1, figure)
drag = DraggableRectangle(rectangle, master, xMinFloat, xMaxFloat - 92)
drag.connect()
app = wx.PySimpleApp()
frame = MplCanvasFrame()
frame.Show(True)
app.MainLoop()
I had a chance to work on this this morning (we are having a 2nd blizzard for the last 3 days). You are right, if you try to redraw the entire figure in the on_motion, it messes up the animation of the yellow rectangle. The key is to also blit the line on the master sub plot.
Try this code out:
import datetime
import numpy as np
import sys
import time
import wx
import matplotlib
from matplotlib.figure import Figure
import matplotlib.dates as mdates
import matplotlib.ticker as mtickers
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import matplotlib.patches as mpatches
class DraggableRectangle:
lock = None
def __init__(self, rect, master, xMin, xMax):
self.rect = rect
self.press = None
self.slave_background = None
self.master_background = None
self.xMax = xMax
self.xMin = xMin
self.master = master
self.master_line, = self.master.get_lines()
def connect(self):
self.cidpress = self.rect.figure.canvas.mpl_connect('button_press_event', self.on_press)
self.cidrelease = self.rect.figure.canvas.mpl_connect('button_release_event', self.on_release)
self.cidmotion = self.rect.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)
def on_press(self, event):
if event.inaxes != self.rect.axes: return
if DraggableRectangle.lock is not None: return
contains, attrd = self.rect.contains(event)
if not contains: return
x0, y0 = self.rect.xy
self.press = x0, y0, event.xdata, event.ydata
DraggableRectangle.lock = self
canvas = self.rect.figure.canvas
axes = self.rect.axes
# set up our animated elements
self.rect.set_animated(True)
self.master_line.set_animated(True)
self.master.xaxis.set_visible(False) #we are not animating this
canvas.draw()
# backgrounds for restoring on animation
self.slave_background = canvas.copy_from_bbox(self.rect.axes.bbox)
self.master_background = canvas.copy_from_bbox(self.master.axes.bbox)
axes.draw_artist(self.rect)
canvas.blit(axes.bbox)
def on_motion(self, event):
if DraggableRectangle.lock is not self: return
if event.inaxes != self.rect.axes: return
x0, y0, xpress, ypress = self.press
dx = event.xdata - xpress
dy = 0
if x0+dx > self.xMax:
self.rect.set_x(self.xMax)
elif x0+dx < self.xMin:
self.rect.set_x(self.xMin)
else:
self.rect.set_x(x0+dx)
self.rect.set_y(y0+dy)
canvas = self.rect.figure.canvas
axes = self.rect.axes
# restore backgrounds
canvas.restore_region(self.slave_background)
canvas.restore_region(self.master_background)
# set our limits for animated line
self.master.set_xlim(self.rect.get_x(), self.rect.get_x() + 92)
# draw yellow box
axes.draw_artist(self.rect)
canvas.blit(axes.bbox)
#draw line
self.master.axes.draw_artist(self.master_line)
canvas.blit(self.master.axes.bbox)
def on_release(self, event):
if DraggableRectangle.lock is not self: return
self.press = None
DraggableRectangle.lock = None
# unanimate rect and lines
self.rect.set_animated(False)
self.master_line.set_animated(False)
self.slave_background = None
self.master_background = None
# redraw whole figure
self.master.xaxis.set_visible(True)
self.rect.figure.canvas.draw()
def disconnect(self):
self.rect.figure.canvas.mpl_disconnect(self.cidpress)
self.rect.figure.canvas.mpl_disconnect(self.cidrelease)
self.rect.figure.canvas.mpl_disconnect(self.cidmotion)
class MplCanvasFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, title='First Chart', size=(800, 700))
datafile = matplotlib.get_example_data('goog.npy')
r = np.load(datafile).view(np.recarray)
datesFloat = matplotlib.dates.date2num(r.date)
figure = Figure()
xMaxDatetime = r.date[len(r.date)-1]
xMinDatetime = r.date[0]
xMaxFloat = datesFloat[len(datesFloat)-1]
xMinFloat = datesFloat[0]
yMin = min(r.adj_close) // 5 * 5
yMax = (1 + max(r.adj_close) // 5) * 5
master = figure.add_subplot(211)
master.plot(datesFloat, r.adj_close)
master.xaxis.set_minor_locator(mdates.MonthLocator())
master.xaxis.set_major_locator(mdates.MonthLocator(bymonth=(1,4,7,10)))
master.xaxis.set_major_formatter(mdates.DateFormatter('%b-%y'))
master.set_xlim(datesFloat[120], datesFloat[120]+92)
master.yaxis.set_minor_locator(mtickers.MultipleLocator(50))
master.yaxis.set_major_locator(mtickers.MultipleLocator(100))
master.set_ylim(yMin, yMax)
master.set_position([0.05,0.20,0.92,0.75])
master.xaxis.grid(True, which='minor')
master.yaxis.grid(True, which='minor')
slave = figure.add_subplot(212, yticks=[])
slave.plot(datesFloat, r.adj_close)
slave.xaxis.set_minor_locator(mdates.MonthLocator())
slave.xaxis.set_major_locator(mdates.YearLocator())
slave.xaxis.set_major_formatter(mdates.DateFormatter('%b-%y'))
slave.set_xlim(xMinDatetime, xMaxDatetime)
slave.set_ylim(yMin, yMax)
slave.set_position([0.05,0.05,0.92,0.10])
rectangle = mpatches.Rectangle((datesFloat[120], yMin), 92, yMax-yMin, facecolor='yellow', alpha = 0.4)
slave.add_patch(rectangle)
canvas = FigureCanvas(self, -1, figure)
drag = DraggableRectangle(rectangle, master, xMinFloat, xMaxFloat - 92)
drag.connect()
app = wx.PySimpleApp()
frame = MplCanvasFrame()
frame.Show(True)
app.MainLoop()

Resources