I'm trying to run a simple code that takes a traffic lights image & displays it as grayscale --> 'Original' and then takes the same image and displays only the parts of it which correspond to the upper and lower thresholds I pre-defined --> 'bright'. However, the following code when I run it, displays nothing.
when I change plt.imshow() to cv2.imshow() it does, so I'm confused as to why this happens. Both libraries are installed correctly. I even tried adding plt.show() at the end of the code, but still no output.
import cv2
import matplotlib.pyplot as plt
original = cv2.imread('traffic_lights.jpeg')
plt.imshow(original,cmap='gray')
lower=150
upper = 254
bright = cv2.inRange(original,lower,upper)
plt.imshow(bright,cmap='gray')
I think you need to specify a figure and axes, then plot the image on the axes.
import cv2
import matplotlib.pyplot as plt
original = cv2.imread('traffic_lights.jpeg')
plt.imshow(original,cmap='gray')
lower = 150
upper = 254
bright = cv2.inRange(original,lower,upper)
fig, ax = plt.subplots()
im = ax.imshow(bright,cmap='gray')
plt.show()
It helps to first convert your image as opencv image into the right color scale with cv2.COLOR_xxx:
import cv2
import matplotlib.pyplot as plt
original = cv2.imread('traffic_light.jpg')
original = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
lower, upper = 150, 254
bright = cv2.inRange(image, lower, upper)
plt.imshow(bright,cmap='gray')
OpenCV imread functions reads the image in a B, G, R fashion.
Therefore if you read the image with imread and want to display with pyplot, first you need to convert the image into the R, G, B then display.
For instance:
import cv2
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv2.imread("lights.jpg")
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)
plt.show()
Result:
If you don't convert using cvtColor the result will be:
The above for the RGB images, for gray images the correct answer will be:
import cv2
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv2.imread("lights.jpg")
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.imshow(img_rgb, cmap='gray')
plt.show()
lower = 150
upper = 254
bright = cv2.inRange(img_rgb, lower, upper)
plt.imshow(bright, cmap='gray')
plt.show()
Result:
Related
program is about removing the gradient background color
Currently it takes about 20 second for single image of size 420X560 size
code is
from colormath.color_objects import sRGBColor, LabColor
from colormath.color_conversions import convert_color
from colormath.color_diff import delta_e_cie2000
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np
import os
import cv2
def backgroundRemovel(url):
img = cv2.imread(url)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)
plt.title('original Image')
plt.show()
color=img[0,0]
firstPixelRGB = sRGBColor(color[0], color[1], color[2], is_upscaled=True);
firstPixelLab = convert_color(firstPixelRGB, LabColor);
t=img.shape
x_dim=t[0]
y_dim=t[1]
for i in range(x_dim):
for j in range(y_dim):
rgbCurPixel=img[i,j]
curPixelRGB=sRGBColor(rgbCurPixel[0], rgbCurPixel[1], rgbCurPixel[2], is_upscaled=True);
curPixelLab=convert_color(curPixelRGB, LabColor);
delta_e = delta_e_cie2000(firstPixelLab, curPixelLab);
#print("difference is "+str(delta_e))
if delta_e<15:
img[i, j] = (0, 0, 0)
return img
fnmae="image.jpeg"
open_cv_image = backgroundRemovel(fname)
plt.imshow(open_cv_image)
plt.title('Background Removed Image')
plt.show()
Input Image:
Desired:
if there is any better way to remove gradient background of image please do share
I have a simple 2d numpy array which is a pixel map of a gray scale image. I am trying to print some parts of the image. My code is
from google.colab import drive
drive.mount('/content/drive')
import numpy as np
import matplotlib.pyplot as plt
import cv2
img = cv2.imread('/content/drive/My Drive/Colab Notebooks/sample2.jpg') # the source file is correctly mounted
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
And
i = 0
while i < (len(roi) - 1): # roi is a list of strictly increasing positive integers
print(roi[i], roi[i+1])
plt.imshow(img_gray[roi[i]:roi[i+1]], cmap='gray')
i += 1
For example if roi = [10, 40, 50, 100], it should prints two parts of the image. But as I run the cell above, it only print one image which is the last part of the image. Is it possible not to overwrite other image and print them all?
You should try calling plt.show() after each plt.imshow(...):
i = 0
while i < (len(roi) - 1): # roi is a list of strictly increasing positive integers
print(roi[i], roi[i+1])
plt.imshow(img_gray[roi[i]:roi[i+1]], cmap='gray')
plt.show() # <----- this will show all plots
i += 1
Or, if you want to keep a nicer, more organized plot, you could use subplots, although you should state how many subplots you want, here is an example with random input:
import matplotlib.pyplot as plt
import numpy as np
ims = np.random.randn(3, 224, 224)
fig, ax = plt.subplots(1, 3)
for i in range(3):
ax[i].imshow(ims[i])
This last example will plot the images arranged horizontally:
I came over the following issue: the resize functions of these two libraries behave differently. Here is a small test:
import numpy as np
import PIL
import cv2
from matplotlib import pyplot as plt
img = np.random.randn(10, 10, 3)
SIZE = (5, 5)
img -= img.min()
img /= img.max()
img = (img*255).astype(np.uint8)
# Display the initial image
plt.figure(figsize=(16,9))
plt.imshow(img)
plt.show()
plt.close()
# resize the image in two different ways
img_cv2 = cv2.resize(img, dsize=SIZE, interpolation=cv2.INTER_LINEAR)
img_pil = PIL.Image.fromarray(img).resize(SIZE, resample=PIL.Image.BILINEAR)
# get the difference image and normalize it
diff = np.abs(img_cv2.astype(np.float32) - img_pil)
diff /= diff.max() or 1
# display results
fig, axs = plt.subplots(1, 3, figsize=(16, 9))
axs[0].imshow(img_cv2)
axs[1].imshow(img_pil)
axs[2].imshow(diff)
plt.show()
plt.close()
My question is now: why is this happening? Is the difference in the implementation (I didn't check the code in PIL or OpenCV yet) or am I using the functions in the wrong way?
Here are some example outputs: Input image and Resized images.
I am having a problem converting an image I;16 to JPEG with PIL.
My original image can be found here (as pickle).
The original image comes from a DICOM file.
Here is the code to try:
import pickle
import matplotlib.pyplot as plt
from PIL import Image
ims = pickle.load(open("pixel_array.pickle", "rb"))
img = Image.fromarray(ims)
print(img.mode)
rgb_im = img.convert("RGB")
print(rgb_im.mode)
fig, ax = plt.subplots(figsize=(20, 10))
ax.imshow(rgb_im, cmap=plt.cm.bone)
fig.show()
Unfortunately the image is completely white, while it should be a chest x-ray scan image.
I followed this other stackoverflow question, and with the following
ims = pickle.load(open("pixel_array.pickle", "rb"))
img = Image.fromarray(ims)
print(img.mode)
img.mode = 'I'
rgb_im = img.point(lambda i:i*(1./256)).convert('L')
rgb_im.save('my.jpeg')
fig, ax = plt.subplots(figsize=(20, 10))
ax.imshow(rgb_im, cmap=plt.cm.bone)
fig.show()
I am able to visualise the image, but unfortunately my.jpeg is a black image. Please help!
Your values are 16-bit and need to be reduced to 8-bit for display. You can scale them from their current range of 2,712 (i.e. ims.min()) to 4,328 (i.e. ims.max()) with the following:
from PIL import Image
import numpy as np
import pickle
# Load image
ims = pickle.load(open("pixel_array.pickle", "rb"))
# Normalise to range 0..255
norm = (ims.astype(np.float)-ims.min())*255.0 / (ims.max()-ims.min())
# Save as 8-bit PNG
Image.fromarray(norm.astype(np.uint8)).save('result.png')
I need to add noise to multiple of coloured images (file format is ppm; source: http://benchmark.ini.rub.de/Dataset/GTSRB_Final_Training_Images.zip) in python. The noised output images should be still in colour.
I tryed the following:
from scipy import misc
import numpy as np
import cv2
import imageio
# Read image ('00000_00030.ppm') from file system
image = misc.imread('./00000/00000_00030.ppm', mode="RGB")
# Add noise to the input image
noised_image = image + 3 * image.std() * np.random.random(image.shape)
# Plot original and noisy images
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 10))
f, axarr = plt.subplots(2, 2)
axarr[0, 0].imshow(image)
axarr[0, 0].set_title('Original image')
axarr[0, 1].imshow(noised_image)
axarr[0, 1].set_title('Noised image')
plt.show()
# Save noised image to file system
saved_image = cv2.imwrite("./noised.ppm", noised_image)
But first of all the problem is that the noised image won't be plotted correctly in jupyter notebook (see figure 1):
figure 1
The second problem is that the RG-channels (Red and Green) were be lost (in saved file):
figure 2
So how can I preserve all RGB colors in noised image?
After searching for a long time I have the solution now - the saved file preserves now all RGB-colours (See Line 8 in following code; see figure 3):
from scipy import misc
import numpy as np
import cv2
import imageio
# Read image ('00000_00030.ppm') from file system
# image = misc.imread('./00000/00000_00030.ppm', mode="RGB")
image = cv2.imread('./00000/00000_00030.ppm',1)
# Add noise to the input image
noised_image = image + 3 * image.std() * np.random.random(image.shape)
# Plot original and noisy images
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 10))
f, axarr = plt.subplots(2, 2)
axarr[0, 0].imshow(image)
axarr[0, 0].set_title('Original image')
axarr[0, 1].imshow(noised_image)
axarr[0, 1].set_title('Noised image')
plt.show()
# Save noised image to file system
saved_image = cv2.imwrite("./noised1.ppm", noised_image)
Figure 3
But the plotted figures are still wrong:
Figure 4
Here is the final Code to add noise to RGB images in python, and plot them correctly:
from scipy import misc
import numpy as np
import cv2
import imageio
# Read image ('00000_00030.ppm') from file system
# image = misc.imread('./00000/00000_00030.ppm', mode="RGB")
image = cv2.imread('./00000/00000_00030.ppm',1)
# Add noise to the input image
noised_image = image + 3 * image.std() * np.random.random(image.shape)
RGB_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# Plot original and noisy images
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 10))
f, axarr = plt.subplots(2, 2)
axarr[0, 0].imshow(RGB_image)
axarr[0, 0].set_title('Original image')
axarr[0, 1].imshow(noised_image)
axarr[0, 1].set_title('Noised image')
plt.show()
# Save noised image to file system
saved_image = cv2.imwrite("./noised1.ppm", noised_image)
This will take the pixel values of the given image and start encoding the noise that you give as input to the least significant bits in the pixel. The image output would vary slightly.
def asciiToBin(ascii):
return ''.join(str(bin(ord(byte)))[2:].zfill(8) for byte in ascii)
def hide(img, data, outName):
dataBin = asciiToBin(data)
pixels, mode = list(img.getdata()), img.mode
newPixels = []
for i in range(len(dataBin)):
newPixel = list(pixels[i])
newPixel[i%len(mode)] = setLSB(newPixel[i%len(mode)], dataBin[i])
newPixels.append(tuple(newPixel))
newData = newPixels + pixels[len(newPixels):]
img.putdata(newData)
img.save(outName, "PNG")
def setLSB(target, value):
binary = str(bin(target))[2:]
if binary[-1] != value:
binary = binary[:-1] + value
return int(binary, 2)