get_shape() and ndims for an image read through opencv - python

I read an image as follows
image_float = cv2.imread('/data/cat.jpg',cv2.IMREAD_UNCHANGED)
The shape of the read image is (1200, 1600, 3).
When this read array is passed to the following code if image.get_shape().ndims != 3:, an error message will appear AttributeError: numpy.ndarray' object has no attribute get_shape
It seems to me that get_shape() and ndims are expecting a Tensorflow tensor. However, I read image using cv2 as the above. How to transform an image read by cv2 to a tensorflow tensor.
Originally, the image is read as follows
rl = ("https://upload.wikimedia.org/wikipedia/commons/d/d9/"
"First_Student_IC_school_bus_202076.jpg")
image_string = urllib2.urlopen(url).read()
image = tf.image.decode_jpeg(image_string, channels=3)
# Convert image to float32 before subtracting the
# mean pixel value
image_float = tf.to_float(image, name='ToFloat')

Try converting it to a tensor first:
image_cv = cv2.imread('/data/cat.jpg', cv2.IMREAD_UNCHANGED)
image_tensor = tf.convert_to_tensor(image_float, dtype=np.int32)
image_float = tf.to_float(image_tensor, name='ToFloat')
BTW why do you need the IMREAD_UNCHANGED flag if it's a JPEG (with no support of alpha channel)?
You can also just ask TF to load the jpeg from that file:
image = tf.image.decode_jpeg(tf.read_file('/data/cat.jpg'), channels=3)

Related

How can i convert images into grayscale?

I have 1000 of images. Now I like to convert those images into grayscale?
import tensorflow as tf
from tensorflow.keras.utils import img_to_array
#df['image_name'] = df['image_name'].apply(str)
df_image = []
for i in tqdm(range(df.shape[0])):
img = image.load_img('/content/drive/MyDrive/Predict DF from Image of Chemical
Structure/2D image/'+df['image_name'][i]+'.png',target_size=(100,100,3))
img = image.img_to_array(img)
img = img/255
df_image.append(img)
X = np.array(df_image)
Per the TensorFlow documentation for tf.keras.utils.load_img, it accepts the argument color_mode, which is
One of "grayscale", "rgb", "rgba". Default: "rgb". The desired image format.
and it also returns "A PIL Image instance.".
The best way to do this is
img = image.load_img(
'/content/drive/MyDrive/Predict DF from Image of Chemical Structure/2D image/'+df['image_name'][i]+'.png',
target_size=(100,100,3),
color_mode="grayscale"
)
If I'm misinterpreting the documentation, the following should also work (put this after load_img but before img_to_array):
img = img.convert("L") # if you need alpha preserved, "LA"
Since this is a PIL Image instance, it has the .convert method. "L" converts the image to just lightness values

Attempt to convert a value (<PIL.Image.Image image mode=RGBA size=5000x5000>) with an unsupported type (<class 'PIL.Image.Image'>) to a Tensor

def preprocess(image_path):
slide = OpenSlide(image_path)
region = (1000,1000)
size = (5000, 5000)
image = slide.read_region(region, 0, size)
image = tf.image.resize(image, (512, 512))
image = np.array(image)
return image
train_x=[]
for i in tqdm(train_df['file_path']):
x1=preprocess(i+i[61:75])
train_x.append(x1)
Why I am getting this below error when I run tf.image.resize(image, (512, 512))
?
ValueError: Attempt to convert a value (<PIL.Image.Image image mode=RGBA size=5000x5000 at 0x7F0CB61EBE90>) with an unsupported type (<class 'PIL.Image.Image'>) to a Tensor.
The slide.read_region(region, 0, size) converts the image file into an "in-memory" representation of an image. The resizing Ops such as tf.image.resize() accept input images as tensors or np.array but you are passing a PIL image which causes the error. Kindly change the preprocess function like below
def preprocess(image_path):
slide = OpenSlide(image_path)
region = (1000,1000)
size = (5000, 5000)
image = slide.read_region(region, 0, size)
# convert the image to np.array
image = tf.image.resize(np.array(image), (512, 512))
return image
I could replicate the error with a single image in colab. Please refer to this gist. Thank you!

How to create a One-hot Encoded Matrix from a PNG for Per Pixel Classification in Tensorflow 2

I'm attempting to train a Unet to provide each pixel of a 256x256 image with a label, similar to the tutorial given here. In the example, the predictions of the Unet are a (128x128x3) output where the 3 denotes one of the classifications assigned to each pixel. In my case, I need a (256x256x10) output having 10 different classifications (Essentially a one-hot encoded array for each pixel in the image).
I can load the images but I'm struggling to convert each image's corresponding segmentation mask to the correct format. I have created DataSets by defining a map function called process_path which takes a saved numpy representation of the mask and creates a tensor of dimension (256 256 10), but I get a ValueError when I call model.fit, telling me that it cannot call as_list because the shape of the Tensor cannot be found:
# --------------------------------------------------------------------------------------
# DECODE A NUMPY .NPY FILE INTO THE REQUIRED FORMAT FOR TRAINING
# --------------------------------------------------------------------------------------
def decode_npy(npy):
filename = npy.numpy()
data = np.load(filename)
data = kerasUtils.to_categorical(data, 10)
return data
# --------------------------------------------------------------------------------------
# DECODE AN IMAGE (PNG) FILE INTO THE REQUIRED FORMAT FOR TRAINING
# --------------------------------------------------------------------------------------
def decode_img(img):
img = tf.image.decode_png(img, channels=3)
return tf.image.convert_image_dtype(img, tf.float32)
# --------------------------------------------------------------------------------------
# PROCESS A FILE PATH FOR THE DATASET
# input - path to an image file
# output - an input image and output mask
# --------------------------------------------------------------------------------------
def process_path(filePath):
parts = tf.strings.split(filePath, '/')
fileName = parts[-1]
parts = tf.strings.split(fileName, '.')
prefix = tf.convert_to_tensor(maskDir, dtype=tf.string)
suffix = tf.convert_to_tensor("-mask.png", dtype=tf.string)
maskFileName = tf.strings.join((parts[-2], suffix))
maskPath = tf.strings.join((prefix, maskFileName), separator='/')
# load the raw data from the file as a string
img = tf.io.read_file(filePath)
img = decode_img(img)
mask = tf.py_function(decode_npy, [maskPath], tf.float32)
return img, mask
trainDataSet = allDataSet.take(trainSize)
trainDataSet = trainDataSet.map(process_path).batch(4)
validDataSet = allDataSet.skip(trainSize)
validDataSet = validDataSet.map(process_path).batch(4)
How can I take each images' corresponding (256 256 3) segmentation mask (stored as png) and convert it to a (256 256 10) tensor, where the i-th channel represents the pixels value as in the tutorial? Can anyone explain how this is achieved, either in the process_path function or wherever it would be most efficient to perform the conversion?
Update:
Here is an example of a segmentation mask. Every mask contains the same 10 colours shown:
import numpy as np
from cv2 import imread
im = imread('hfoa7.png', 0) # read as grayscale to get 10 unique values
n_classes = 10
one_hot = np.zeros((im.shape[0], im.shape[1], n_classes))
for i, unique_value in enumerate(np.unique(im)):
one_hot[:, :, i][im == unique_value] = 1
hfao7 is the name of the image you posted. This code snippet creates a one-hot matrix from the image.
You will want to insert this code into decode_npy(). However, since you sent me a png, the code above won't work with a npy file. You could pass in the names of the pngs instead of the npys instead. Don't worry about using kerasUtils.to_categorical - the function I posted makes categorical labels.
You can do this in pure Tensorflow, see my Blogpost: https://www.spacefish.biz/2020/11/rgb-segmentation-masks-to-classes-in-tensorflow/

How to fix datatype mismatch to predict images using my trained model?

I trained a CNN, but I'm unable to use it to make predictions.
All of my images are in a folder
model = tf.keras.models.load_model("C:\Sid\CNNs\MoonRocks.h5")
import os
filepath = "C:\Sid\Projects\LunarMoonRocks\DataSet\Test Images"
for img in os.listdir(filepath):
img_path = os.path.join(filepath, img)
img_array=cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
new_array=cv2.resize(img_array, (480, 480))
img_tbp = new_array.reshape(-1, 480, 480, 1)
prediction = model.predict([img_tbp])
This code shows the error
TypeError: Value passed to parameter 'input' has DataType uint8 not in list of allowed values: float16, bfloat16, float32, float64
I tried to change the image type to float32 using
image = tf.image.decode_jpeg(img_tbp)
image = tf.cast(image, tf.float32)
But that showed the error
ValueError: Failed to convert a NumPy array to a Tensor (Unsupported object type int).
How do I get my model to predict the images in the folder?
decode_jpeg is used to decode the contents of image file which is read in binary format. You have already read your image file using OpenCV and OpenCV reads the file in NumPy format. Had you made use of read_file, then you should have used decode_jpeg.
Now coming to your problem, you could have converted your uint8 image to floating type either by just using tf.cast operation as you had done it, but you have most likely forgotten to normalize your image from the range of [0, 255] in uint8 to [0, 1] in float. So you could have directly converted your image to float and bring the number's value in range of [0, 1] using:
image = image / 255.0

dlib face detection error : Unsupported image type, must be 8bit gray or RGB image

i am trying to crop out the faces from instagram avatars by first detecting the faces and then resizing the image. i am reading all the images which have been stored in a dataframe and then creating a numpy array. Then i am running a frontal face detector which returns me an object but when i call the object it returns me the error stated. i tried giving only colored images as input but that did not work neither did try and except. Here is the code:
df = pd.read_csv('/home/instaurls2.csv')
img_width, img_height = 139, 139
confidence = 0.8
#graph = K.get_session().graph
data1 = np.array([io.imread(row[1]) for row in df.itertuples()])
#print(data1)
detector = dlib.get_frontal_face_detector()
print (detector)
dets=detector(data1,1) # **error arrives here**
print (dets)
output=None
for i, d in enumerate(dets):
data1 = data1[d.top():d.bottom(), d.left():d.right()]
data1 = resize(data1, (img_width, img_height))
output = np.expand_dims(data1, axis=0)
print (output)
Opencv reads image as BGR per default.
You can read images with cv2:
import cv2
cv2.imread(image_filepath)
This worked for me:
image.astype('uint8')

Categories

Resources