Rotate an image without averaging pixel values - python

Is it possible to rotate an image and keep the true values? When I rotate a black and white image I get back grey values. Can I rotate without averaging the pixel values? I can almost do it manually by using np.where() but it gets difficult when there are more than 2 pixel values.
Code:
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
from scipy import ndimage
import cv2
filename = 'rot square.png'
img = cv2.imread('square test.png')
img_rot = ndimage.rotate(img, 10, reshape = False)
cv2.imwrite(filename, img_rot)
Original Image
Rotated Image
Averaged Values
True Values

Here:
from PIL import Image
img = Image.open('original.png')
rotated = img.rotate(45)
rotated.save('rotated.png')

Related

How to create a grey image in python?

I tried to create a grey 3x3 pixel image in python, however the result is always a black image with several coloured pixels.
What I tried:
import numpy as np
from PIL import Image
greyimg = np.array([[[128]*3]*3]*3)
print(greyimg)
Image.fromarray(greyimg, 'RGB').save("test_grey.png")
What I expected:
a grey 3x3 image
What I got:
a coloured image
import numpy as np
from PIL import Image
import cv2
greyimg = np.array([[[128]*3]*3]*3,dtype=np.uint8)
print(greyimg)
Image.fromarray(greyimg, 'RGB').save("test_grey.png")

Remove small objects from binary image with skimage

I have the following binary image and I want to remove the spots with a value 0 inside the area of the pixels with value 1.
I tried following code from the skimage package:
im1 = morphology.remove_small_objects(img_test, 500, connectivity=1)
But the code does not do anything. The picture stays the same, no mater how I change the parameters.
Where is my mistake?
import numpy as np
import matplotlib.pyplot as plt
# image posted by OP
URL = "https://i.stack.imgur.com/Pa7Io.png"
# Read image
from skimage import io
from skimage.filters import threshold_otsu
from skimage.color import rgb2gray
image = rgb2gray(io.imread(URL)[21:899, 555:1125, :3]) #index cut the needed part
# Convert to True-False
_2color = image > threshold_otsu(image)
# accumulated true from left to right. Is true if any pixel to the left is True
trueLeft = np.logical_or.accumulate(_2color, axis=1)
# accumulated true from right to left. Is True if any pixel to the right is True
trueRight = np.logical_or.accumulate(_2color[:, ::-1], axis=1)[:, ::-1]
# True if has any true in the left and right
orImage = trueLeft * trueRight
plt.imshow(orImage)
plt.show()

Crop region of interest from binary image using python

Requirement is to crop region of interest from binary image.
I need a rectangle image from a binary image by removing the extra space around the region of interest.
For example:
From this Original image i want only the region of interest marked with yellow color rectangle.
Note: Yellow color rectangle is just for the reference and it is not present in the image that will be processed.
I tried the following python code but it is not giving the required output.
from PIL import Image
from skimage.io import imread
from skimage.morphology import convex_hull_image
import numpy as np
from matplotlib import pyplot as plt
from skimage import io
from skimage.color import rgb2gray
im = imread('binaryImageEdited.png')
plt.imshow(im)
plt.title('input image')
plt.show()
# create a binary image
im1 = 1 - rgb2gray(im)
threshold = 0.8
im1[im1 <= threshold] = 0
im1[im1 > threshold] = 1
chull = convex_hull_image(im1)
plt.imshow(chull)
plt.title('convex hull in the binary image')
plt.show()
imageBox = Image.fromarray((chull*255).astype(np.uint8)).getbbox()
cropped = Image.fromarray(im).crop(imageBox)
cropped.save('L_2d_cropped.png')
plt.imshow(cropped)
plt.show()
Thank you.
Your image is not actually binary on account of two things:
firstly, it has 26 colours, and
secondly it has an (entirely unnecessary) alpha channel.
You can trim it like this:
#!/usr/bin/env python3
from PIL import Image, ImageOps
# Open image and ensure greysale and discard useless alpha channel
im = Image.open("thing.png").convert('L')
# Threshold and invert image as not actually binary
thresh = im.point(lambda p: p < 64 and 255)
# Get bounding box of thresholded image
bbox1 = thresh.getbbox()
crop1 = thresh.crop(bbox1)
# Invert and crop again
crop1n = ImageOps.invert(crop1)
bbox2 = crop1n.getbbox()
crop2 = crop1.crop(bbox2) # You don't actually need this - it's just for debug
# Trim original, unthresholded, uninverted image to the two bounding boxes
result = im.crop(bbox1).crop(bbox2)
result.save('result.png')
even i have similar problem. Also it would be helpful if image saved is in 32X32 px.

Resize image with skimage library without stretching

Hey i am trying to resize an image without stretching it but adding white pixels instead. I looked arround but i found nothing specifying how that can be achieved from within skimage. So instead i used numpy to add the extra pixels before the resize as arrays of [float(255)].
from skimage.io import imread
from skimage.io import imsave
from skimage.transform import resize
from matplotlib import pyplot as plt
from pylab import cm
import numpy as np
from skimage import morphology
from skimage import measure
from scipy import misc
def process(file_):
im = imread(file_, as_grey=True)
#im = misc.imread(file_)
#im=np.fromfile(file_, dtype=np.int64)
#Filler to avoid stretching
orig_rows, orig_cols = im.shape
print orig_rows, orig_cols
if orig_rows < orig_cols:
for addition in range(0,orig_cols-orig_rows):
#adding white rows
lst = np.array(list(float(255) for x in range(0,orig_cols)))
im= np.vstack((im,lst))
if orig_rows > orig_cols:
for addition in range(0,orig_rows-orig_cols):
#adding white columns
lst = np.array(list([float(255)] for x in range(0,orig_rows)))
im= np.hstack((im,lst))
image = resize(im, (48, 48))
imsave('test.jpg',im)
imsave('test1.jpg',image)
plt.imshow(im, cmap=cm.gray)
plt.show()
When i view the image with pyplot it looks like this
We can see that the columns have been added, but after i save the image with
image = resize(im, (48, 48))
imsave('test.jpg',im)
imsave('test1.jpg',image)
The the images look like negatives, and the resized image looks completely white(next to the dark its invisible on the sites background). Any ideas?
The code below should work. Note that the padded areas' color is not exactly white in order to see the image boundaries in the uploaded image. For white padding set fill_cval = np.max(img).
def resize_padded(img, new_shape, fill_cval=None, order=1):
import numpy as np
from skimage.transform import resize
if fill_cval is None:
fill_cval = np.max(img)
ratio = np.min([n / i for n, i in zip(new_shape, img.shape)])
interm_shape = np.rint([s * ratio for s in img.shape]).astype(np.int)
interm_img = resize(img, interm_shape, order=order, cval=fill_cval)
new_img = np.empty(new_shape, dtype=interm_img.dtype)
new_img.fill(fill_cval)
pad = [(n - s) >> 1 for n, s in zip(new_shape, interm_shape)]
new_img[[slice(p, -p, None) if 0 != p else slice(None, None, None)
for p in pad]] = interm_img
return new_img
import numpy as np
import matplotlib.pylab as plt
from skimage.data import astronaut
from skimage.color import rgb2gray # using luminance
from skimage.io import imsave
img = rgb2gray(astronaut())
# set desired image size
out_size = (30, 100) # height, width
# set the color of the padded area. Here: "95% luminance"
fill_cval = np.max(img) * 0.95
resized_img = resize_padded(img, out_size, fill_cval=fill_cval)
imsave('img.png', img)
imsave('img_res.png', resized_img)

How to compute colored pixel area on images using Python?

import numpy as np
from matplotlib import cm
from matplotlib import pyplot as plt
import Image
from scipy import ndimage
import Image, ImageDraw
import PIL
import cv
import cv2
from scipy.ndimage import measurements, morphology
from PIL import Image
from numpy import *
from scipy.ndimage import filters
import pylab
img = np.asarray(Image.open('test.tif').convert('L')) #read and convert image
img = 1 * (img < 127) # threshold
plt.imshow(img, cmap=cm.Greys_r) # show as black and white
plt.show()
Code above gives white pixels on black background, how to compute white region on image, then to split image into 100 rectangles and find rectangles with min, max and average numbers of pixels? thanks
Since your image is binary you can just sum the values to get a count of the white pixels.
from PIL import Image
import numpy as np
img = np.asarray(Image.open("foo.jpg").convert('L'))
img = 1 * (img < 127)
m,n = img.shape
# use np.sum to count white pixels
print("{} white pixels, out of {} pixels in total.".format(img.sum(), m*n))
# use slicing to count any sub part, for example from rows 300-320 and columns 400-440
print("{} white pixels in rectangle.".format(img[300:320,400:440].sum()))
Use slicing to pick out any rectangle and use sum() on that part.

Categories