removing images with specific size using python - python

i have a folder with lots of jpg images. and i need to delete all the pictures which have size les than 160*160.i tried couple of codes in python my self. but they didn't work and i don't know what to do about it.
import os
from PIL import Image
folder_images = "dataset/PetImages/Cat"
for filenames in os.walk(folder_images):
img = Image.open(filenames)
h, w = img.shape
if(not (h >= 160 or w >= 160)):
os.remove(img)
here is the error i get:
fp = io.BytesIO(fp.read())
AttributeError: 'tuple' object has no attribute 'read'

Your mistake is that Image.open() returns an Image object, but os.remove() needs the path of file, not an Image object.
So here img should be replaced by filenames or something indicating the path of image.
Maybe you should read the documents carefully:
https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.open
https://docs.python.org/3/library/os.html#os.remove
By the way, an PIL.image object do not has shape attribute, what you need is size.

You're trying to open a list of images instead of just 1 image. Moreover, os.remove(img) is not correct since img is a PIL.image object instead of a filepath as #Sinon has mentioned already. Try this instead:
import os
from PIL import Image
folder_images = "dataset/PetImages/Cat"
for _, _, image_filenames in os.walk(folder_images):
for image_filename in image_filenames:
img = Image.open(image_filename)
h, w = img.size
if(not (h >= 160 or w >= 160)):
os.remove(image_filename)

Related

Stitching multiple pngs into a h5 image h5py

I created an model in blender. From here I took 2d slices through the y-plane of that model leading to the following.
600 png files each corresponding to a ylocation i.e y=0, y=0.1 etc
Each png file has a resolution of 500 x 600.
I am now trying to merge the 600 pngs into a h5 file using python before loading the .h5 into some software. I find that each individual png file is read fine and looks great. However when I look at the final 3d image there is some stretching of the image, and im not sure how this is being created.
The images are resized (from 600x600 to 500x600, but I have checked and this is not the cause of the stretching). I would like to know why I am introducing such stretching in other planes (not y-plane).
Here is my code, please note that there is some work in progress here, hence why I append the dataset to a list (this is to be used for later code)
from PIL import Image
import sys
import os
import h5py
import numpy as np
import cv2
from datetime import datetime
dir_path = os.path.dirname(os.path.realpath(__file__))
sys.path.append(dir_path + '//..//..')
Xlen=500
Ylen=600
Zlen=600
directory=dir_path+"/LowPolyA21/"
for filename in os.listdir(directory):
if fnmatch.fnmatch(filename, '*.png'):
image = Image.open(directory+filename)
new_image = image.resize((Zlen, Xlen))
new_image.save(directory+filename)
dataset = np.zeros((Xlen, Zlen, Ylen), np.float)
# traverse all the pictures under the specified address
cnt_num = 0
img_list = sorted(os.listdir(directory))
os.chdir(directory)
for img in (img_list):
if img.endswith(".png"):
gray_img = cv2.imread(img, 0)
dataset[:, :, cnt_num] = gray_img
cnt_num += 1
dataset[dataset == 0] = -1
dataset=dataset.swapaxes(1,2)
datasetlist=[]
datasetlist.append(dataset)
dz_dy_dz = (float(0.001),float(0.001),float(0.001))
for j in range(Xlen):
for k in range(Ylen):
for l in range(Zlen):
if datasetlist[i][j,k,l]>1:
datasetlist[i][j,k,l]=1
now = datetime.now()
timestamp = now.strftime("%d%m%Y_%H%M%S%f")
out_h5_path='voxelA_'+timestamp+'_flipped'
out_h5_path2='voxelA_'+timestamp+'_flipped.h5'
with h5py.File(out_h5_path2, 'w') as f:
f.attrs['dx_dy_dz'] = dz_dy_dz
f['data'] = datasetlist[i] # Write data to the file's primary key data below
Example of image without stretching (in y-plane)
Example of image with stretching (in x-plane)

How to solve this error: AttributeError: 'numpy.ndarray' object has no attribute 'crop'

I want to crop images with different sizes to get the same size to futher process them. I wrote the following code:
import glob
import cv2
import os
from matplotlib import pyplot as plt
inputFolder = "C:\\Users\\die5k\\Desktop\\hist\\Cropping\\input"
storeDirectory = "C:\\Users\\die5k\\Desktop\\hist\\Cropping\\output"
path = glob.glob(inputFolder + "\\*.png")
cv_img = []
image_no = 1
for img in path:
n = cv2.imread(img)
cv_img.append(n)
print(img)
os.chdir(storeDirectory)
cropped_img = n.crop(((w-100)//2, (h-100)//2, (w+100)//2, (h+100)//2))
filename = "Figure_" + str(image_no) + ".png"
plt.gcf().savefig(filename)
print(image_no)
image_no += 1
This outputs me the following error: AttributeError: 'numpy.ndarray' object has no attribute 'crop'
I am coding beginner and I dont know what I have to do.
It's because numpy doesn't have crop functionality. Try opening the image using PIL library and use the crop function as follows:
from PIL import Image
n = Image.open(path)
And then proceed with the crop.
Or Alternatively, you can crop it yourself without the function as follows:
cropped_img = n[((h-100)//2):((h-100)//2)+((h+100)//2), ((w-100)//2):((w-100)//2)+((w+100)//2)]

How can I remove EXIF data from a dataset?

I am trying to remove EXIF data from images in a dataset (which I will use in transfer learning). However, it does not seem to be working. Below is my code:
import os
from PIL import Image
import piexif
import imghdr
from tqdm import tqdm
import warnings
Folder = 'drive/My Drive/PetImages'
labels =['Dog', 'Cat']
for label in labels:
imageFolder = os.path.join(Folder, label)
listImages = os.listdir(imageFolder)
for img in tqdm(listImages):
imgPath = os.path.join(imageFolder,img)
try:
img = Image.open(imgPath)
data = list(img.getdata())
image_without_exif = Image.new(img.mode, img.size)
image_without_exif.putdata(data)
image_without_exif.save(img)
print("done")
except:
print("except")
I tried saving the image using PIL (as per a previously asked question: Python: Remove Exif info from images) but the output is purely composed of "except"s.
I tried again using the piexif module, as below:
# Same imports as above
Folder = 'drive/My Drive/PetImages'
labels =['Dog', 'Cat']
for label in labels:
imageFolder = os.path.join(Folder, label)
listImages = os.listdir(imageFolder)
for img in tqdm(listImages):
imgPath = os.path.join(imageFolder,img)
try:
ImageType = img.format
# warnings.filterwarnings("error")
if ImageType in ["JPEG", "TIF", "WAV"]:
exif_data = img._getexif()
print(exif_data)
piexif.remove(img)
print("done")
except:
print("except")
In the code above, I check for the image type first to make sure the method _getexif() actually exists, then I just remove the data after saving it in exif_data variable. The output consisted of "except"s and the occasional exif data (in the form of a dictionary) or "None" if it doesn't exist but never the word "done". Why doesn't it reach that part?
For anyone stumbling upon this through Google, there is a simple solution using PIL:
from PIL import Image
im = Image.open('some-image.jpg')
# this clears all exif data
im.getexif().clear()
im.save('some-image-without-exif.jpg')
I thought that getexif() only allows read access as the name might imply, but it turns out that this is not the case.
Edit: In my case, it even worked to just load and save the file, without im.getexif().clear(). I don't know how reliable that is, though.
That command definitely removes exif-data from the image-object, though. This can be simply tested in a Python shell:
>>> from PIL import Image
>>> im = Image.open('some-image.jpg')
>>> print(im.getexif())
{296: 2, 282: 72.0, 283: 72.0 ..... }
>>> im.getexif().clear()
>>> print(im.getexif())
{}

OpenCV does not accept ndarray to TextDecectorCNN.detect()

I am trying to use this OpenCV class of text detector to find out if I can use it for my project. I am loaging image like this:
src = cv2.imread(img_path)
And then I am trying to use function mentioned before like this:
bbox, confidence = cv2.text_TextDetectorCNN.detect(src)
But this code falls with the following mistake:
TypeError: descriptor 'detect' for 'cv2.text_TextDetectorCNN' objects doesn't apply to a 'numpy.ndarray' object
I have already tried to use image = cv2.cvtColor(src, cv2.COLOR_BGR2RGB, cv2.CV_8UC3) but it doesn't do a thing - image remains an ndarray.
UPD: Attaching whole code and problematic picture.
import os
# borrowed from https://github.com/lengstrom/fast-style-transfer/blob/master/src/utils.py
def list_images(in_path, formats=[".jpg", ".jpeg", ".gif", ".png", ".pgm", ".bmp"]):
img_files = []
for (dirpath, _, filenames) in os.walk(in_path):
for file in filenames:
_, ext = os.path.splitext(file)
ext = str.lower(ext)
if ext in formats:
img_files.append(os.path.join(dirpath, file))
return img_files
def test_accuracy(folder_path):
image_list = list_images(folder_path)
for img_path in image_list:
src = cv2.imread(img_path)
bbox, confidence = cv2.text_TextDetectorCNN.detect(src)
print(img_path, bbox, confidence) # To check format of output
Tested image:
(I've tested 3 different .jpg images, none of them worked)
Question: is there a way to convert ndarray into some OpenCV format that will be accepted by mentioned function?
Your problem is that you don't create an instance of your text detector. See this:
import cv2
import numpy as np
# After downloading the caffemodel and
# textbox.prototxt you have to create
# an instance of your model
textSpotter = cv2.text.TextDetectorCNN_create(
"textbox.prototxt", "TextBoxes_icdar13.caffemodel"
)
src = cv2.imread("1.png")
bbox, confidence = textSpotter.detect(src)
print("HELLO", bbox, confidence) # To check format of output

Python copy on PIL image object

I'm trying to create a set of thumbnails, each one separately downscaled from the original image.
image = Image.open(path)
image = image.crop((left, upper, right, lower))
for size in sizes:
temp = copy.copy(image)
temp.thumbnail((size, height), Image.ANTIALIAS)
temp.save('%s%s%s.%s' % (path, name, size, format), quality=95)
The above code seemed to work fine but while testing I discovered that some images (I can't tell what's special about them, maybe only for PNG) raise this error:
/usr/local/lib/python2.6/site-packages/PIL/PngImagePlugin.py in read(self=<PIL.PngImagePlugin.PngStream instance>)
line: s = self.fp.read(8)
<type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'read'
Without the copy() these images work just fine.
I could just open and crop the image anew for every thumbnail, but I'd rather have a better solution.
I guess copy.copy() does not work for the PIL Image class. Try using Image.copy() instead, since it is there for a reason:
image = Image.open(path)
image = image.crop((left, upper, right, lower))
for size in sizes:
temp = image.copy() # <-- Instead of copy.copy(image)
temp.thumbnail((size, height), Image.ANTIALIAS)
temp.save('%s%s%s.%s' % (path, name, size, format), quality=95)

Categories

Resources