When I open a FULLY WHITE file with pillow (from PIL import Image) and then obtain the color of all of the pixels, you SHOULD see something like [255, 255, 255, 255, 255, 255]..... but instead i only see [0, 0, 0, 0, 0, 0]....., code is as follows:
from PIL import Image
image = Image.open("index.png", "r")
pixels = list(image.getdata())
print(pixels)
Your code doesn't convert white pixels values to black pixels. It somehow represents pixel values in different way. We can check whether it converts white pixel values to black pixels using RGB color domain. Code is shown below:
from PIL import Image
import numpy as np
img = Image.open("index.png") # open colour image
imgRgb = img.convert('RGB')
pixels = list(imgRgb.getdata())
width, height = imgRgb.size
pixels = np.asarray([pixels[i * width:(i + 1) * width] for i in range(height)], dtype=int)
Related
I am trying to improve the quality of an image using python. How can I get white and black more clearer so as to enhance the quality of the image
Here's my try
from PIL import Image
def enhance_image(img):
black = (0, 0, 0)
white = (255, 255, 255)
threshold = (138, 138, 138)
img = Image.open(img).convert("LA")
pixels = img.getdata()
newPixels = []
for pixel in pixels:
if pixel < threshold:
newPixels.append(black)
else:
newPixels.append(white)
newImg = Image.new("RGB",img.size)
newImg.putdata(newPixels)
newImg.save("MyTemp.jpg")
Here's a sample image
Is their any way to change the colors of a binary image in to other two different colors other than black and white using python. How to achieve this if the input binary image is "unit8" datatype and when the same input image is of "bool" datatype?
d = gdal.Open(....)
band = d.GetRasterBand(1)
arr1 = band.ReadAsArray()
thresh = threshold_otsu(arr1)
binary = arr1 > thresh
plt.imshow(binary)
well, generally speaking, given you have an x,y image and thus array of bool type; you need to generate a (x,y,3) array like with numpy:
colImage = np.zeros((x,y,3), dtype="uint8")
the dimension with 3 encodes the color with rgb, so
colImage[:,:,0] = boolImage * 255 # for red
colImage[:,:,1] = boolimage * 255 # for green
colImage[:,:,2] = boolimage * 255 # for blue
if i remember correctly. the * 255 is to get from the boolean "1" to the 8bit maximum of 255
You could do it with a palette, but here I make a full RGB version.
from PIL import Image
from skimage import data
from skimage.filters import threshold_otsu
# Load image
image = data.camera()
# Threshold image to binary
thresh = threshold_otsu(image)
binary = image > thresh
# Make 3 channel RGB image same dimensions
RGB = np.zeros((binary.shape[0],binary.shape[1],3), dtype=np.uint8)
# Make True pixels red
RGB[binary] = [255,0,0]
# Make False pixels blue
RGB[~binary] = [0,0,255]
# Display result
Image.fromarray(RGB).show()
You can express the same thing slightly differently like this:
from skimage import data
from skimage.filters import threshold_otsu
# Load image
image = data.camera()
# Threshold image to binary
thresh = threshold_otsu(image)
binary = image > thresh
# Define red and blue
red = np.array([255,0,0],dtype=np.uint8)
blue = np.array([0,0,255],dtype=np.uint8)
# Make RGB array, pre-filled with blue
RGB = np.zeros((binary.shape[0],binary.shape[1],3), dtype=np.uint8) + blue
# Overwrite with red where threshold exceeded, i.e. where mask is True
RGB[binary] = red
Storing a full RGB image for just 2 colours is rather wasteful of space though, because you have 3 bytes (R, G and B) per pixel. It is probably preferable to make a palettised image where you just store 1 byte per pixel and use that byte as an index into a palette that can hold 256 colours. You can do that like this:
from PIL import Image
from skimage import data
from skimage.filters import threshold_otsu
# Load image
image = data.camera()
# Threshold image to binary
thresh = threshold_otsu(image)
binary = image > thresh
# Make a palette with 2 entries, magenta and yellow
palette = [
255, 0, 255, # magenta
255, 255, 0 # yellow
]
# Zero-pad the palette to 256 RGB colours, i.e. 768 values
palette += (768-len(palette))*[0]
# Make PIL/Pillow image from the binary array
p = Image.fromarray((binary*1).astype(np.uint8))
# Push the palette into image and save
p.putpalette(palette)
p.save('result.png')
I am using python, OpenCV and Numpy. My goal is to find all white pixel and turn it red and turn everything else off or white. My code:
import numpy as np
import cv2
import matplotlib.pyplot as plt
# Read mask
image = cv2.imread("path to my image")
any_white = np.any(image == [255,255,255], axis = -1)
image[any_white]=[255,0,0]
plt.imshow(image)
plt.show()
cv2.imwrite('result.png',image)
Problem 1: Targetting any [255,255,255] doesn't find all, whiteist, I starting finding any [244,244,244], [243,243,243] and so on. Is there a way to set a range of white, maybe from [255,255,255] to [230,230,230]?
Problem 2: clearly, with plt.imshow(image) and plt.show() within python, the result shows red, but when i used cv2.imwrite('result.png',image) to save, it's blue. See result image.
Problem 1:
You can create a mask and set the red channel to False so that you keep the value at 255 if you want to target only the white pixels
mask_bg = (image == [255, 255, 255])
mask_bg[:, :, 0] = False # set red channel mask to false (leave 255 value)
image[mask_bg] = 0 # set all white pixels to [255, 0, 0]
If you want to find all values in a range you can use cv2.inRange:
mask = cv2.inRange(image, (230, 230, 230), (255, 255,255))
Problem 2:
OpenCV uses BGR as default instead of RGB, you can convert from BGR to RGB with:
new_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
cv2.imshow('BGR Image', new_image )
Keep in mind that if you open an image with OpenCV it will be BGR, so convert it before manipulating the channels.
Problem 1:
The pixels you are planning to target may not have the exact value of (255, 255, 255). Hence it is better to binarize the image by setting a range of pixel values. You can find the exact range by creating Trackbars and tuning them manually. You can find more about implementing Trackbars in OpenCV here.
Problem 2:
This happens because OpenCV uses BGR or (Blue, Green, Red) colorspace by default. You can change the colorspace into RGB or (Red, Green, Blue) by using cv2.cvtColor(image, cv2.COLOR_BGR2RGB) before saving.
How can we replace all the black color from a video to white.
I tried this but its not working
import cv2
import numpy as np
from matplotlib import pyplot as plt
cap = cv2.VideoCapture(0)
while(1):
ret, img = cap.read()
#Remove all black color and replace it with white
img[np.where((img == [0,0,0]).all(axis = 2))] = [255,255,255]
The following code snippet shows how to replace all black pixels in a BGR image with white using only Numpy. You can apply it to each frame of your video.
import numpy as np
a = np.zeros((100,100, 3), dtype= np.uint8) # Original image. Here we use a black image but you can replace it with your video frame.
white = np.full((100, 100, 3), 255, dtype=np.uint8) # White image
a = np.where(a[:,:] == [0,0,0], white, a) # This is where we replace black pixels.
Please note that this will only replace true black pixels. In a real-world video, you'd do some thresholding as a pre-processing step as it is very rare to have perfectly black pixels.
EDIT:
To affect dark pixels under a certain value but not necessarily completely black, use thresholding:
# We make all pixels with value lower than 100 into black pixels.
# This only works with grayscale images.
a = cv2.cvtColor(a, cv.COLOR_BGR2GRAY) # Convert image to grayscale
ret, a = cv2.threshold(a, 100, 255, cv2.THRESH_TOZERO) # Make gray pixels under 100 black.
This only works for grayscale images but maybe you should consider converting your image from BGR to grayscale in any case if your goal is to detect black pixels to turn them into white.
So basically I have a colored RGB image and I want to add a colored overlay over the RGB image without converting it to gray level.
For example if I have a colored image(RGB). And I want to add a transparent blue color over the index like this
img[200:350, 200:350] = [0, 0, 1] # Blue block
This question is a sibling question to this one:
Applying a coloured overlay to an image in either PIL or Imagemagik
Difference is the color space. The above question is for gray level images rather colored (RGB).
from skimage import io, data
import numpy as np
img = data.astronaut()
Please use the above code to answer.
Here is the code in OpenCV:
import cv2
# load the image
image = cv2.imread("2.jpg")
# I resized the images because they were to big
image = cv2.resize(image, (0,0), fx=0.75, fy=0.75)
overlay = image.copy()
output = image.copy()
#select the region that has to be overlaid
cv2.rectangle(overlay, (420, 205), (595, 385),(0, 255, 255), -1)
#Adding the transparency parameter
alpha = 1
#Performing image overlay
cv2.addWeighted(overlay, alpha, output, 1 - alpha,0, output)
#Save the overlaid image
cv2.imwrite('Output'+str(alpha) +'.jpg', output)
cv2.waitKey(0)
cv2.destroyAllWindows()
Some results:
when alpha = 0.1
when alpha = 0.5
when alpha = 0.8
when alpha = 1.0 (the overlay is no longer transparent but opaque)