I am using Scikits SSIM to calculate how similar 2 pictures are, and it is working fine for one exception. When there is a lot of white pixels (lets say its a pure white background with a very simple black outlined shape) it will say they are very similar when the actual shape is in fact very different.
I tried looking for other questions about this but couldn't find one that accurately answered my question.
Some code:
from skimage.measure import compare_ssim
import numpy as np
import cv2
# With SSIM, compares image A to image B, and returns the result.
def compare_images(imageA, imageB):
return compare_ssim(imageA, imageB)
# Loads an image with a given filepath with imread.
def load_images(filepath):
picture = cv2.imread(filepath)
# Convert the images to grayscale
return cv2.cvtColor(picture, cv2.COLOR_BGR2GRAY)
# compare the images
original = load_images("images/images.png")
contrast = load_images("images/download.png")
result = compare_images(original, contrast)
print(result)
Mind you, I am just a Python novice. Any help would be welcome.
Related
So I have an image and I want to cut it up into multiple images to feed into OCR to read.
image example
I only want the messages with the white bubbles and exclude anything with the grey bubbles. I can't figure out how to make a loop to separate each white bubble.
import numpy as np
from PIL import ImageGrab, Image, ImageFilter
img = Image.open('test1.png').convert('RGB')
na = np.array(img)
orig = na.copy()
img = img.filter(ImageFilter.MedianFilter(3))
whiteY, whiteX = np.where(np.all(na==[255,255,255],axis=2))
top, bottom = whiteY[1], whiteY[-1]
left, right = whiteX[1], whiteX[-1]
You could try using the opencv threshold function, followed by the findContours function. This will, if you threshold the image correctly, give you the 'borders' of the bubbles above. Using that, you could then crop out each text bubble.
Here's a simple example of contours being used:
https://www.geeksforgeeks.org/find-and-draw-contours-using-opencv-python/
Otherwise if you'd like to understand better how the opencv functions I mentioned or those that are used in the article above, have a look at the opencv documentation.
I am new to Python and not really sure how to attack this problem.
What I am trying to do is to take a black and white image and change the value of the edge (x pixels thick) from 255 to some other greyscale value.
I need to do this to a set of png images inside of a folder. All images will be geometric (mostly a combination of straight lines) no crazy curves or patterns. Using Python 3.
Please check the images.
A typical file will look like this:
https://drive.google.com/open?id=13ls1pikNsO7ZbsHatC6cOr4O6Fj0MPOZ
I think this is what you want. The comments should explain pretty well what I going on:
#!/usr/bin/env python3
import numpy as np
from PIL import Image, ImageFilter
from skimage.morphology import dilation, square
# Open input image and ensure it is greyscale
image = Image.open('XYbase.png').convert('L')
# Find the edges
edges = image.filter(ImageFilter.FIND_EDGES)
# Convert edges to Numpy array and dilate (fatten) with our square structuring element
selem = square(6)
fatedges = dilation(np.array(edges),selem)
# Make Numpy version of our original image and set all fatedges to brightness 128
imnp = np.array(image)
imnp[np.nonzero(fatedges)] = 128
# Convert Numpy image back to PIL image and save
Image.fromarray(imnp).save('result.png')
So, if I start with this image:
The (intermediate) edges look like this:
And I get this as the result:
If you want the outlines fatter/thinner, increase/decrease the 6 in:
selem = square(6)
If you want the outlines lighter/darker, increase/decrease the 128 in:
imnp[np.nonzero(fatedges)] = 128
Keywords: image, image processing, fatten, thicken, outline, trace, edge, highlight, Numpy, PIL, Pillow, edge, edges, morphology, structuring element, skimage, scikit-image, erode, erosion, dilate, dilation.
I can interpret your question in a much simpler way, so I thought I'd answer that simpler question too. Maybe you already have a grey-ish edge around your shapes (like the Google drive files you shared) and just want to change all pixels that are neither black nor white into a different colour - and the fact that they are edges is irrelevant. That is much easier:
#!/usr/bin/env python3
import numpy as np
from PIL import Image
# Open input image and ensure it is greyscale
image = Image.open('XYBase.png').convert('L')
# Make Numpy version
imnp = np.array(image)
# Set all pixels that are neither black nor white to 220
imnp[(imnp>0) & (imnp<255)] = 220
# Convert Numpy image back to PIL image and save
Image.fromarray(imnp).save('result.png')
I have an image. I want to get the perimeter of every object in my image. For example, in this image , the perimeter of an object is 33 (the number of pixels at its edges).
I have written the following algorithm, but it is very timely.
Does anyone have an idea to increase the speed of the algorithm?
What I have tried:
def cal_perimeter_object(object, image):
peri_ = 0
for pixel_ in image:
if pixel_is_in_neigbor_of_object() is True:
peri_ += 1
return peri_
As mentioned in the comment by #Piinthesky having a boolean (or labelled image) where you know the label for the object you want to find the contour for is the first step. There are a number of ways of doing this, the simplest of which is thresholding. Once you have your labelled image you can find the perimeter in a number of ways - e.g. the number of pixels along the border. To give you a head start here is a way to do it on the image you put in the link. I have used scikit-image but there are other python libraries you may use.
# If your python version is not 3.x uncomment line below
#from __future__ import print_function
from skimage.measure import label, regionprops
import skimage.io as io
# read in the image (enter the path where you downloaded it on your computer below
im = io.imread('/home/kola/Downloads/perimeter.png')
# To simplify things I am only using the first channel and thresholding
# to get a boolean image
bw = im[:,:,0] > 230
regions = regionprops(bw.astype(int))
print(regions[0].perimeter)
I have a three dimensional binary image for which I am working on determining the two-point cluster function. The first step to doing this is to define all of the connected regions within the image. I have successfully done so with skimage as:
from skimage.measure import label
from skimage.morphology import remove_small_objects
from skimage.measure import label
from skimage.morphology import remove_small_objects
min = 64
label_file = label(newim_int, return_num=True, connectivity=2)
image_clean = remove_small_objects(label_file[0], min_size=min,connectivity=2, in_place=True)
label_file = label(image_clean, return_num=True, connectivity=2)
with a bunch of stuff missing to read in the file, etc between min= and label_file=
I would now like to know the distribution of sizes of the regions labeled
here. Unfortunately, skimage.measure.regionprops tells me it only works for 2D images. Is there another way to do this?
Thanks
regionprops has already started being expanded to include 3d images; at present some of the properties return a NotImplementedError.
Fortunately, area already works for 3d so you should be able to use this property.
I have an image saved by another code of mine. The image is a normal JPG file. I saved it with imsave.
now when I'm reading it in another code, it seems to be 3d :S
the image is here.
and a simple code to read it is this :
import mahotas
img = mahotas.imread('d:/normal.jpg')
print img.shape, img.dtype
Try reading the jpg as greyscale like this:
mahotas.imread('d:/normal.jpg', as_grey = True)
(Author of mahotas here).
The suggestion by Junuxx is correct:
mahotas.imread('file.jpg', as_grey=True)
This reads the RGB file and converts it to grey scale by a weighted average of the components (they are not equally weighted, but use typical coefficients that attempt to be perceptually more accurate).
The alternative (which I rather prefer) is:
im = mahotas.imread('file.jpg')
im = im[:,:,0]
I assume that all the channels have the same values and just use the first one.