how to save figure in vis_bbox without white background, when plotting with matplotlib? - matplotlib

i'm trying to save the image after vis_bbox prediction with its original image dimension.
my code:
from PIL import Image, ImageChops
import cv2
img = utils.read_image('/home/ubuntu/ui.jpg', color=True)
bboxes, labels,scores = model.predict([img])
bbox, label, score = bboxes[0], labels[0], scores[0],
colors = voc_colormap(label + 1)
bccd_labels = ('cell', 'cell')
vis_bbox(img, bbox, label_names=bccd_labels, instance_colors=colors, alpha=0.9, linewidth=1.0)
plt.axis("off")
plt.savefig("/home/ubuntu/ins.jpg")
while saving , it saves the image with white background and default size (432 *288).
i need to save the predicted image from vis_bbox with the original dimension (1300 *1300).
Any suggestions would be helpful!

Related

Rotating image using rotation matrix in Python

So I am trying to create a code that can rotate an image counterclockwise using Python by implementing the rotation matrix. This code is supposed to rotate the image counterclockwise, but why does it rotate the picture in a clockwise motion?
import math
import numpy as np
from PIL import Image
img = Image.open('squidward.jpg')
Im = np.array(img)
angle = 30
# Define the most occuring variables
angle=math.radians(angle) #converting degrees to radians
cosine=math.cos(angle)
sine=math.sin(angle)
height=Im.shape[0] #define the height of the image
width=Im.shape[1] #define the width of the image
# Define the height and width of the new image that is to be formed
new_height = round(abs(Im.shape[0]*cosine)+abs(Im.shape[1]*sine))+1
new_width = round(abs(Im.shape[1]*cosine)+abs(Im.shape[0]*sine))+1
# define another image variable of dimensions of new_height and new _column filled with zeros
Rot_Im=np.zeros((new_height,new_width,Im.shape[2]))
# Find the centre of the image about which we have to rotate the image
original_centre_height = round(((Im.shape[0]+1)/2)-1) #with respect to the original image
original_centre_width = round(((Im.shape[1]+1)/2)-1) #with respect to the original image
# Find the centre of the new image that will be obtained
new_centre_height= round((((new_height)+1)/2)-1) #with respect to the new image
new_centre_width= round((((new_width)+1)/2)-1) #with respect to the new image
for i in range(height):
for j in range(width):
#co-ordinates of pixel with respect to the centre of original image
y0=Im.shape[0]-1-i-original_centre_height
x0=Im.shape[1]-1-j-original_centre_width
#co-ordinate of pixel with respect to the rotated image
new_y0=round(x0*sine+y0*cosine)
new_x0=round(x0*cosine-y0*sine)
'''since image will be rotated the centre will change too,
so to adust to that we will need to change new_x and new_y with respect to the new centre'''
new_y0=new_centre_height-new_y0
new_x0=new_centre_width-new_x0
# adding if check to prevent any errors in the processing
if 0 <= new_x0 < new_width and 0 <= new_y0 < new_height and new_x0>=0 and new_y0>=0:
Rot_Im[new_y0,new_x0,:]=Im[i,j,:] #writing the pixels to the new destination in the output image
pil_img=Image.fromarray((Rot_Im).astype(np.uint8)) # converting array to image
pil_img.save("rotated_image.png") # saving the image
Do -30 for counterclockwise. I think you will get the answer but it is too late i suppose

How to numpy.tile a PIL image without changing original size?

I'm trying to speed up tiling a PIL image converted to a NumPy array, without changing the size of the image.
The input is an image of x,y dimensions and the output is an image of same x, y dimensions but with the image inside tiled.
This is what I used to did first without numpy:
import numpy
from PIL import Image
def tile_image(texture, texture_tiling = (5, 5)):
#texture is a PIL image, for e.g. Image.open(filename)
width, height = texture.size
tile = texture.copy()
tiled_texture = Image.new('RGBA', (width*texture_tiling[0], height*texture_tiling[1]))
for x in range(texture_tiling[0]):
for y in range(texture_tiling[1]):
x_ = width*x
y_ = height*y
tiled_texture.paste(tile, (x_, y_))
tiled_texture = tiled_texture.resize(texture.size, Image.BILINEAR)
return tiled_texture
This is the function with numpy:
def tile_image(texture, texture_tiling = (5, 5)):
tile = numpy.array(texture.copy())
tile = numpy.tile(tile, (texture_tiling[1], texture_tiling[0], 1))
tile = Image.fromarray(tile)
tile = tile.resize(texture.size, Image.BILINEAR)
return tile
The problem with both of these is that it requires increasing the image size before resizing them, but this becomes difficult with higher resolution textures. But trying to use a for loop and replacing pixels at [x, y] with [(texture_tiling[0]*x)%width, (texture_tiling[1]*y)%height] is way too slow using a regular for loop. What do I do to speed up the above pixel operation?
NOTE: I don't try resizing the tile to be smaller than paste on an empty layer, because the tiling could be odd and mess up the tile size.

Images and masks visualisation - Colab

Hei everyone.
I have set up an image and mask visual check in Colab using matplotlib, NumPy and Random and it was expected to print the same image number for both (image and mask), but unfortunately, it's not.
For whatever reason, the images don't correspond. Both images have the same size and number/name.
Does anyone have some hints on how to fix this? Thank you in advance!
import random
import numpy as np
image_number = random.randint(0,len(image_dataset))
plt.figure(figsize=(12,6))
plt.subplot(121)
plt.imshow(np.reshape(image_dataset[image_number], (patch_size,patch_size,3)))
plt.subplot(122)
plt.imshow(np.reshape(mask_dataset[image_number], (patch_size,patch_size,3)))
plt.show()
image printed using the code above
This is how I'm importing the training images. (doing the same for masks)
images_dataset = [] #TRAIN IMAGES
for path, subdirs, files in os.walk(root_directory):
dirname = path.split(os.path.sep)[-1]
if dirname =="images":
images = os.listdir(path)
for i, image_name in enumerate(images):
if image_name.endswith('.png'):
image = cv2.imread(path + "/" + image_name, 1)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
SIZE_X = (image.shape[1]//patch_size)*patch_size
SIZE_Y = (image.shape[0]//patch_size)*patch_size
image = Image.fromarray(image)
image = image.crop((0,0,SIZE_X, SIZE_Y))
image = np.array(image)
try to sort out the data.
images = sorted(os.listdir(path))

Wrote a code in python to edit an image's background and the output i am getting is totally off

I edited it to view the foreground image on a white background but now, none of the images are visible.
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('91_photo.jpg')
mask = np.zeros(img.shape[:2],np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (10,10,360,480)
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask==2)|(mask==0),0,255).astype('uint8')
img = img*mask2[:,:,np.newaxis]
plt.imshow(img),plt.colorbar(),plt.show()
Expecting the result to be a visible image on a white background
This is what i'm getting
There are a number of small issues with your code that are adding up to that weird result.
OpenCV uses BGR ordering of the channels of an image, where matplotlib uses RGB. That means if you read an image with OpenCV but want to display with matplotlib, you need to convert the image from BGR to RGB before displaying (that's the reason the colors are weird). Also, not that important, but color images are not displayed with a colormap, so showing the colormap does not do anything for you.
In numpy, it's best to keep masks boolean whenever you can, because you can use them to index your arrays. Your current code converts a boolean mask to a uint8 image with 0 and 255 values and then you multiply that with your image. That means your image will be set to zero wherever the mask is zero---and your image values will explode (or do weird stuff with overflow). Instead, keep the mask boolean and use it to index your array. That way anywhere the mask is True you can just set the value in your image to something specific (like 255 for white).
This should fix you up:
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('91_photo.jpg')
mask = np.zeros(img.shape[:2], np.uint8)
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
rect = (10, 10, 360, 480)
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)
mask2 = (mask==2) | (mask==0)
img[mask2] = 255
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)
plt.show()

plot several image files in matplotlib subplots

I would like to create a matrix subplot and display each BMP files, from a directory, in a different subplot, but I cannot find the appropriate solution for my problem, could somebody helping me?.
This the code that I have:
import os, sys
from PIL import Image
import matplotlib.pyplot as plt
from glob import glob
bmps = glob('*trace*.bmp')
fig, axes = plt.subplots(3, 3)
for arch in bmps:
i = Image.open(arch)
iar = np.array(i)
for i in range(3):
for j in range(3):
axes[i, j].plot(iar)
plt.subplots_adjust(wspace=0, hspace=0)
plt.show()
I am having the following error after executing:
natively matplotlib only supports PNG images, see http://matplotlib.org/users/image_tutorial.html
then the way is always read the image - plot the image
read image
img1 = mpimg.imread('stinkbug1.png')
img2 = mpimg.imread('stinkbug2.png')
plot image (2 subplots)
plt.figure(1)
plt.subplot(211)
plt.imshow(img1)
plt.subplot(212)
plt.imshow(img2)
plt.show()
follow the tutorial on http://matplotlib.org/users/image_tutorial.html (because of the import libraries)
here is a thread on plotting bmps with matplotlib: Why bmp image displayed as wrong color with plt.imshow of matplotlib on IPython-notebook?
The bmp has three color channels, plus the height and width, giving it a shape of (h,w,3). I believe plotting the image gives you an error because the plot only accepts two dimensions. You could grayscale the image, which would produce a matrix of only two dimensions (h,w).
Without knowing the dimensions of the images, you could do something like this:
for idx, arch in enumerate(bmps):
i = idx % 3 # Get subplot row
j = idx // 3 # Get subplot column
image = Image.open(arch)
iar_shp = np.array(image).shape # Get h,w dimensions
image = image.convert('L') # convert to grayscale
# Load grayscale matrix, reshape to dimensions of color bmp
iar = np.array(image.getdata()).reshape(iar_shp[0], iar_shp[1])
axes[i, j].plot(iar)
plt.subplots_adjust(wspace=0, hspace=0)
plt.show()