I used this code to read series of png format images in a folder. but it reads only one image successfully. What is the reason for that?
from glob import glob
for fn in glob('*.png'):
im = cv2.imread(fn)
You've only got one variable (called im) so it can only hold one image. You probably want a list of images:
# Make empty list
imgs = []
for fn in glob('*.png'):
im = cv2.imread(fn, cv2.IMREAD_COLOR)
imgs.append(im)
Or, you can use a "list comprehension":
imgs = [ cv2.imread(fn, cv2.IMREAD_COLOR) for fn in glob('*.png') ]
Related
as we know, in Keras it is possible to use many functions like ImageDataGenerator or dataset_from_image to generate a train/test data from directories.
In my situation, the data is organized in the following way:
/hog_features
/train_data
/class_a
a1.npy
a2.npy
...
/class_b
b1.npy
b2.npy
...
/class_c
c1.npy
c2.npy
...
/test_data
/class_a
a1.npy
a2.npy
...
/class_b
b1.npy
b2.npy
...
/class_c
c1.npy
c2.npy
...
I would like to ask if someone can help me to know how to find an appropriate way to create a generator for the data in order to compile a CNN (Conv1D) model.
Notes: The .npy files are vectors (288,).
a non-elegant solution is to recreate the dataset with the files in jpg format. Code below can convert a jpg image to .npy (to_jpg=False) or npy to jpg (to_jpg=True).
Then use ImageDataGenerator.flow_from_directory as your generator. I will assume your dataset is in C:\hog_features. I set to name for the directory to hold the converted images to C:\jpg
import os
import numpy as np
import shutil
import cv2
from tqdm import tqdm
def converter(train_path, test_path, destination_dir, to_jpg):
# if destination_dir exists, erase it and start with an expty directory
if os.path.isdir(destination_dir):
shutil.rmtree(destination_dir)
os.mkdir(destination_dir)
dataset_list = [train_path, test_path]
names=['train_data', 'test_data']
zipped_list=zip(names, dataset_list)
for name, dataset in zipped_list:
dest_dataset_path=os.path.join(destination_dir, name)
os.mkdir(dest_dataset_path) # make train and test directories in destination directory
classes=os.listdir(dataset)
for klass in classes:
class_path=os.path.join(dataset, klass)
dest_class_path=os.path.join(dest_dataset_path, klass)
os.mkdir(dest_class_path)
flist=os.listdir(class_path)
desc=f'{name:10s}-{klass:10s}'
for f in tqdm(flist,ncols=110, unit='file', desc=desc, colour='blue'): # iterate through files in the class
fpath=os.path.join(class_path,f)
index=f.rfind('.')
fname=f[:index]
if to_jpg:
# convert from npy to jpg
img=np.load(fpath) # assuming the .npy images are in rgb format
#img=cv2.cvtColor(img, cv2.COLOR_RGB2BGR) #convert to bgr image format
fname=fname + ".jpg"
dest_fpath=os.path.join(dest_class_path, fname)
img=cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
cv2.imwrite(dest_fpath, img)
else:
#convert from jpg to npy
img=cv2.imread(fpath)
img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #convert to rgb image format
dest_fpath=os.path.join(dest_class_path, fname)
np.save(dest_fpath, img)
train_path=r'C:\hog_featurestrain_data'
test_path = r'C:\hog_features\test_data'
destination_dir=r'C:\Temp\people\jpg'
to_jpg=True
converter(train_path, test_path, destination_dir, to_jpg)
When i convert images to greyscale with pil it rotates them.
How do i disable this?
from PIL import Image
import os
path = 'spanish_pages_photos/'
pathContents = os.listdir(path)
list = []
# get file names and append to list
for i in pathContents:
list.append(i)
list = sorted(list)
#loop through and change to grey scale
for i in list[2:]:
img = Image.open(f'spanish_pages_photos/{i}').convert('L')
img.save(f'spanish_pages_photos/{i}')
print('finished')
The EXIF data can contain an "EXIF Orientation" field. Try auto-orienting with PIL.ImageOps.exif_transpose().
See here.
I have a simple code, that applies effect on one of my pictures:
from matplotlib import pyplot as plt
import os
import cv2
path_in=os.path.join("C:/Users/Desktop/Images","glass.jpg")
img = cv2.imread(path_in, cv2.IMREAD_COLOR)
img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)
plt.show()
but problem is, that I want to apply this to all images in my folder and I don't know their names.
So I understand that I need to create loop with the list of my images in folder, but I have tried this and it didn't work
path_in=os.path.join("C:/Users/Desktop/Images")
list = os.listdir(path_in)
for img in list:
img = cv2.imread(path_in, cv2.IMREAD_COLOR)
img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
io.imsave("C:/Users/Desktop/Images_new", image_converted)
plt.imshow(img)
plt.show()
I would be very glad if someone could tell me, what I am doing wrong. Thank you
You are already on the right track. There are just a few minor issues with your code:
First, define the path_in inside the loop and join your folder path with the image name. Second, never use keywords from the python language as variable names. The name list is a python keyword.
I don't know the functions imsave, imshow and show in details, so I'm not sure if they should be inside of the loop. I guess, but there you may need to just test it. Also, for imsave, it may be that you need to set a path for each image. In that case you could do it like io.imsave("C:/Users/Desktop/Images_new/{}".format(img), image_converted).
path_folder = "C:/Users/Desktop/Images"
img_list = os.listdir(path_in)
for img in img_list:
path_in = os.path.join(path_folder, img)
img = cv2.imread(path_in, cv2.IMREAD_COLOR)
img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
io.imsave("C:/Users/Desktop/Images_new", image_converted)
plt.imshow(img)
plt.show()
No 100% guarantee it works exaclty as is. Let me know if you get an error.
path_folder = "C:/Users/Desktop/Images"
img_list = os.listdir(path_in)
for img in img_list:
path_in=os.path.join("C:/Users/Desktop/Images",img)
path_out = os.path.join("C:/Users/Desktop/Images_new", img)
img = cv2.imread(path_in, cv2.IMREAD_COLOR)
image_converted = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
io.imsave(path_out, image_converted, format = 'jpg')
plt.imshow(image_converted)
plt.show()
I've face this problem when figuring out how to export external images in blender script. But I guess this is not related straight to blender anymore, more to numpy and how to handle arrays. Here is post about first problem.
So the problem is that when saving numpy array to image it will distorted and there is multiple same images. Look below image for a better understanding.
The goal is trying to figure out how to make this work with numpy and python using the blender's own pixel data. So avoiding to use libraries like PIL or cv2 that do not include in blender python.
When saving data where is images that all is final size works correctly. And when trying to merge 4 smaller pieces to final larger image it not exported correctly.
I've done example script with python in blender to demonstrate the problem:
# Example script to show how to merge external images in Blender
# using numpy. In this example we use 4 images (2x2) that should
# be merged to one actual final image.
# Regular (not cropped render borders) seems to work fine but
# how to merge cropped images properly???
#
# Usage: Just run script and it will export image named "MERGED_IMAGE"
# to root of this project folder and you'll see what's the problem.
import bpy, os
import numpy as np
ctx = bpy.context
scn = ctx.scene
print('START')
# Get all image files
def get_files_in_folder(path):
path = bpy.path.abspath(path)
render_files = []
for root, dirs, files in os.walk(path):
for file in files:
if (file.lower().endswith(('.png', '.jpg', '.jpeg', '.tiff', '.bmp', '.gif'))):
render_files.append(file)
return render_files
def merge_images(image_files, image_cropped = True):
image_pixels = []
final_image_pixels = 0
print(image_files)
for file in image_files:
if image_cropped is True:
filepath = bpy.path.abspath('//Cropped\\' + file)
else:
filepath = bpy.path.abspath('//Regular\\' + file)
loaded_pixels = bpy.data.images.load(filepath, check_existing=True).pixels
image_pixels.append(loaded_pixels)
np_array = np.array(image_pixels)
# Merge images
if image_cropped:
final_image_pixels = np_array
# HOW MERGE PROPERLY WHEN USING CROPPED IMAGES???
else:
for arr in np_array:
final_image_pixels += arr
# Save output image
output_image = bpy.data.images.new('MERGED_IMAGE', alpha=True, width=256, height=256)
output_image.file_format = 'PNG'
output_image.alpha_mode = 'STRAIGHT'
output_image.pixels = final_image_pixels.ravel()
output_image.filepath_raw = bpy.path.abspath("//MERGED_IMAGE.png")
output_image.save()
images_cropped = get_files_in_folder("//Cropped")
images_regular = get_files_in_folder('//Regular')
# Change between these to get different example
merge_images(images_cropped)
#merge_images(images_regular, False)
print('END')
So I guess the problem is related to how to handle image pixel data and arrays with numpy.
Here is project folder in zip file that contains working test script example, where you can test how this works in blender. https://drive.google.com/file/d/1R4G_fubEzFWbHZMLtAAES-QsRhKyLKWb/view?usp=sharing
Since all of your images are the same dimension of 128x128, and since OpenCV images are Numpy arrays, here are three methods. You can save the image using cv2.imwrite.
Input images:
Method #1: np.hstack + np.vstack
hstack1 = np.hstack((image1, image2))
hstack2 = np.hstack((image3, image4))
hstack_result = np.vstack((hstack1, hstack2))
Method #2: np.concatenate
concatenate1 = np.concatenate((image1, image2), axis=1)
concatenate2 = np.concatenate((image3, image4), axis=1)
concatenate_result = np.concatenate((concatenate1, concatenate2), axis=0)
Method #3: cv2.hconcat + cv2.vconcat
hconcat1 = cv2.hconcat([image1, image2])
hconcat2 = cv2.hconcat([image3, image4])
hconcat_result = cv2.vconcat([hconcat1, hconcat2])
Result should be the same for all methods
Full code
import cv2
import numpy as np
# Load images
image1 = cv2.imread('Fart_1_2.png')
image2 = cv2.imread('Fart_2_2.png')
image3 = cv2.imread('Fart_1_1.png')
image4 = cv2.imread('Fart_2_1.png')
# Method #1
hstack1 = np.hstack((image1, image2))
hstack2 = np.hstack((image3, image4))
hstack_result = np.vstack((hstack1, hstack2))
# Method #2
concatenate1 = np.concatenate((image1, image2), axis=1)
concatenate2 = np.concatenate((image3, image4), axis=1)
concatenate_result = np.concatenate((concatenate1, concatenate2), axis=0)
# Method #3
hconcat1 = cv2.hconcat([image1, image2])
hconcat2 = cv2.hconcat([image3, image4])
hconcat_result = cv2.vconcat([hconcat1, hconcat2])
# Display
cv2.imshow('concatenate_result', concatenate_result)
cv2.imshow('hstack_result', hstack_result)
cv2.imshow('hconcat_result', hconcat_result)
cv2.waitKey()
So basically I'm trying to convert a set of RGB images to grayscale using cv2.cvtColor and python is throwing the following error:
Traceback (most recent call last):
File "MCG.py", line 53, in
gray = cv2.cvtColor(data, cv2.COLOR_BGR2GRAY)
TypeError: src is not a numpy array, neither a scalar.
This here is the code:
import numpy as np
import cv2
import dlib
import sys
import skimage
from PIL import Image
import os
import glob
folderpath = sys.argv[1]
cascPath = sys.argv[2]
imageformat = ".tif"
path = folderpath
imfilelist = [os.path.join(path,f) for f in os.listdir(path) if f.endswith(imageformat)]
data = []
for IMG in imfilelist:
print IMG
image = cv2.imread(IMG)
data.append(image)
cv2.imshow('Image', image)
cv2.waitKey(0)
faceCascade = cv2.CascadeClassifier(cascPath)
predictor = dlib.shape_predictor(PREDICTOR_PATH)
gray = cv2.cvtColor(data, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.05,
minNeighbors=5,
minSize=(100,100)
)
As you can see, I'm trying to append all these images to a list, which will then be converted using the cv2.cvtColor function. However, that error is thrown. What am I doing wrong? Thank you.
P.S if anyone is wondering why I imported modules that don't seem to be used in this code, this code is just a segment of the whole thing and all of those modules have are being utilized in one way or the other.
If you read the cv2.cvtColor documentation, you can see that the first parameter is the Src 8-bit single channel image. However, in your case you are giving an entire list of images.
So change the code as
gray = []
for j in range(0,len(data)):
gray.append(cv2.cvtColor(np.array(data[j]), cv2.COLOR_BGR2GRAY))
I guess this should work.
You are collecting the images into a list with
data = []
for IMG in imfilelist:
...
data.append(image)
....
and then trying to convert the list with
gray = cv2.cvtColor(data, cv2.COLOR_BGR2GRAY)
This is why you are getting the error - the error is telling you that data is not an image (numpy array) but is a list. You need to convert one image at a time with cv2.cvtColor().
You could try
gray = []
for img in data:
gray.append(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY))
This would give you a list of greyscaled images, which is what I think you want to do.