I am having some problems opening some .tif files that I have. I've tried using pillow, gdal, cv2, and skimage. I would prefer to use pillow since I do use it in other scripts. I cannot use rasterio becuase when I set up a batch file rasterio throws an gdal._version error that I have yet to solve.
This opening image error is strange to me since I had another code that split raster images (had a missing data issue so I switched to this one) that uses gdal and has no problem opening it. I read a few posts about how pillow does not support certain data types, but I have not any work arounds yet. I've attached the properties of my image and will continue to trouble shoot.
Is there anything that pops out that I need to fix? Again I would prefer to use the first code block I posted (using pillow).
Pillow
import os
from PIL import Image
from itertools import product
def tile(filename, dir_in, dir_out, d):
Image.MAX_IMAGE_PIXELS = None
name, ext = os.path.splitext(filename)
img = Image.open(os.path.join(dir_in, filename))
w, h = img.size
grid = list(product(range(0, h - h % d, d), range(0, w - w % d, d)))
for i, j in grid:
box = (j, i, j + d, i + d)
out = os.path.join(dir_out, f'{name}_{i}_{j}{ext}')
img.crop(box).save(out)
tile('name.tif',
r'D:\image',
r'D:\images_split',
1000)
Traceback (most recent call last):
File "C:/Users/delete_NA/split.py", line 22, in <module>
1000)
File "C:/Users/delete_NA/split.py", line 9, in tile
img = Image.open(os.path.join(dir_in, filename))
File "C:\Users\anaconda3\envs\split\lib\site-packages\PIL\Image.py", line 2959, in open
"cannot identify image file %r" % (filename if filename else fp)
PIL.UnidentifiedImageError: cannot identify image file 'D:\\image\\image_to_split.tif'
GDAL
import os
import gdal
from itertools import product
def tile(filename, dir_in, dir_out, d):
Image.MAX_IMAGE_PIXELS = None
name, ext = os.path.splitext(filename)
img = gdal.Open(os.path.join(dir_in, filename))
w, h = img.size
grid = list(product(range(0, h - h % d, d), range(0, w - w % d, d)))
for i, j in grid:
box = (j, i, j + d, i + d)
out = os.path.join(dir_out, f'{name}_{i}_{j}{ext}')
img.crop(box).save(out)
tile('name.tif',
r'D:\image',
r'D:\images_split',
1000)
Traceback (most recent call last):
File "C:/Users/delete_NA/split.py", line 22, in <module>
1000)
File "C:/Users/delete_NA/split.py", line 10, in tile
w, h = img.size
File "C:\Users\anaconda3\envs\split\lib\site-packages\osgeo\gdal.py", line 2184, in <lambda>
__getattr__ = lambda self, name: _swig_getattr(self, Dataset, name)
File "C:\Users\anaconda3\envs\split\lib\site-packages\osgeo\gdal.py", line 80, in _swig_getattr
raise AttributeError("'%s' object has no attribute '%s'" % (class_type.__name__, name))
AttributeError: 'Dataset' object has no attribute 'size'
Other split code with gdal - this one works
import os
from osgeo import gdal
# import variables
# Setting the directory
os.chdir(r"D:\ortho")
# Loading in the image
rimg = gdal.Open("image.tif")
# Upper left corner of the minX and maxY
gt = rimg.GetGeoTransform()
xmin = gt[0]
ymax = gt[3]
res = gt[1]
xlen = res * rimg.RasterXSize # units is important UTM or WGS
ylen = res * rimg.RasterYSize
# how many tiles you want to have in each row and column
xdiv = 150
ydiv = 150
# Determining the size of each new image
xsize = xlen/xdiv
ysize = ylen/ydiv
print(xsize)
print(ysize)
xsteps = [xmin + xsize * i for i in range(xdiv+1)] # plut because we start in the left top corner where X is at its lowest
ysteps = [ymax - ysize * i for i in range(ydiv+1)] # minus because we start in the left top corner where Y is at its highest
for i in range(xdiv):
for j in range(ydiv):
xmin = xsteps[i]
xmax = xsteps[i+1]
ymax = ysteps[j]
ymin = ysteps[j+1]
# Splices the image up into the set divs and saves them.
gdal.Warp("D:/split_images/item" + str(i)+str(j) + ".tif",rimg,
outputBounds = (xmin,ymin,xmax,ymax),dstNodata = -9999)
Tif Properties Images
Edits
I ran another image through that is a fraction of the size, with the same properties. Same CRS, Units, Data type, ect. I don't think it would be a size issue because I pass Image.MAX_IMAGE_PIXELS = None. One thing to note though, each image that is split, the CRS is not being assigned, which does cause an issue for me later on.
After some digging I found that Image.open() from pillow does not support BigTiffs. It also only supports specific byte sizes. tifffile can be used to open BigTiffs. I ended up changing a couple things in my code. First, using tifffile instead of pillow. Second, changing img.size to img.shape. Third, tifffile opens the image into a numpy array, so use the clip method instead. The code does work, though it is not being clipped. This answers my initial question though.
import os
import tifffile
from itertools import product
def tile(filename, dir_in, dir_out, d):
name, ext = os.path.splitext(filename)
img = tifffile.imread(os.path.join(dir_in, filename))
w = img.shape[0]
h = img.shape[1]
grid = list(product(range(0, h - h % d, d), range(0, w - w % d, d)))
for i, j in grid:
box = (j, i, j + d, i + d)
out = os.path.join(dir_out, f'{name}_{i}_{j}{ext}')
img = img.clip(box)
img = img.astype('uint8')
tifffile.imsave(out, img)
tile('name.tif',
r'D:\image',
r'D:\images_split',
1000)
Related
I need change all images in docx file. How can i do it?
Now i download images with changing but i want change in docx
import zipfile
from PIL import Image, ImageDraw #Подключим необходимые библиотеки.
def change_img(path):
image = Image.open(path) # Открываем изображение.
draw = ImageDraw.Draw(image) # Создаем инструмент для рисования.
pix = image.load() # Выгружаем значения пикселей.
for i in range(image.size[0]):
for j in range(image.size[1]):
a = []
for k in range(3):
a.append(pix[i, j][k])
a = sum(a) // 3
draw.point((i, j), (a, a, a))
return image
archive = zipfile.ZipFile('document.docx')
for file in archive.filelist:
if file.filename.startswith('word/media/'):
change_img(str(archive.extract(file)))
When I am processing a bunch of images, on one of them I get this error
File "/home/tensorflowpython/firstmodel/yololoss.py", line 153, in data_generator
image, box = get_random_data(annotation_lines[i], input_shape, random=True)
File "/home/tensorflowpython/firstmodel/yololoss.py", line 226, in get_random_data
image = image.resize((nw,nh), Image.BICUBIC)
File "/home/tensorflowpython/kenv/lib/python3.6/site-packages/PIL/Image.py", line 1858, in resize
self.load()
File "/home/tensorflowpython/kenv/lib/python3.6/site-packages/PIL/ImageFile.py", line 247, in load
"(%d bytes not processed)" % len(b)
OSError: image file is truncated (25 bytes not processed)
I have already tried the solution suggested here but it doesn't work
my code looks like this
from PIL import Image
def get_random_data(annotation_line, input_shape, random=True, max_boxes=20, jitter=.3, hue=.1, sat=1.5, val=1.5, proc_img=True):
Image.LOAD_TRUNCATED_IMAGES = True
line = annotation_line.split()
image = Image.open(line[0])
iw, ih = image.size
h, w = input_shape
box = np.array([np.array(list(map(int,box.split(',')))) for box in line[1:]])
try:
image.load()
except IOError:
pass # You can always log it to logger
if not random:
# resize image
scale = min(w/iw, h/ih)
nw = int(iw*scale)
nh = int(ih*scale)
dx = (w-nw)//2
dy = (h-nh)//2
image_data=0
if proc_img:
image = image.resize((nw,nh), Image.BICUBIC)
new_image = Image.new('RGB', (w,h), (128,128,128))
new_image.paste(image, (dx, dy))
image_data = np.array(new_image)/255.
# correct boxes
box_data = np.zeros((max_boxes,5))
if len(box)>0:
np.random.shuffle(box)
if len(box)>max_boxes: box = box[:max_boxes]
box[:, [0,2]] = box[:, [0,2]]*scale + dx
box[:, [1,3]] = box[:, [1,3]]*scale + dy
box_data[:len(box)] = box
return image_data, box_data
# resize image
new_ar = w/h * rand(1-jitter,1+jitter)/rand(1-jitter,1+jitter)
scale = rand(.25, 2)
if new_ar < 1:
nh = int(scale*h)
nw = int(nh*new_ar)
else:
nw = int(scale*w)
nh = int(nw/new_ar)
image = image.resize((nw,nh), Image.BICUBIC) #error occurs here
The difference between my error and the previous solution is, mine says OS error and the solution is for IO error
EDIT: I have figured out the image that is causing this error, it can be downloaded from this link
I tried the solution that you linked with the truncated image and it worked. You made a slight mistake when trying to apply this solution: you have to set ImageFile.LOAD_TRUNCATED_IMAGES=True, not Image.LOAD_TRUNCATED_IMAGES.
LOAD_TRUNCATED_IMAGES does not originally exist in Image module, so when you do Image.LOAD_TRUNCATED_IMAGES=True you set a new variable which is not used by the library.
So I think you juste have to do that:
from PIL import ImageFile, Image
ImageFile.LOAD_TRUNCATED_IMAGES = True
image = Image.open("00090.jpg")
# resize now doesn't fail
image.resize((h, w), Image.BICUBIC)
I am trying to read and image using OpenCV and after reading that image I have got some data which I have to save in a CSV file using numpy. Here is the program:-
import cv2 as cv
import numpy as np
import os
img1 = cv.imread('C:/Users/sbans/Pictures/bird.jpg')
dataA1 = os.path.basename('C:/Users/sbans/Pictures/bird.jpg')
height, width, channels = img1.shape
dataA2 = height
dataA3 = width
dataA4 = channels
a = int(height/2)
b = int(width/2)
px1 = img1[a,b]
dataA5 = px1[0]
dataA6 = px1[1]
dataA7 = px1[2]
a = np.array([dataA1, dataA2, dataA3, dataA4, dataA5, dataA6, dataA7])
img2 = cv.imread('C:/Users/sbans/Pictures/cat.jpg')
dataB1 = os.path.basename('C:/Users/sbans/Pictures/cat.jpg')
height, width, channels = img2.shape
dataB2 = height
dataB3 = width
dataB4 = channels
a = int(height/2)
b = int(width/2)
px2 = img2[a,b]
dataB5 = px2[0]
dataB6 = px2[1]
dataB7 = px2[2]
b = np.array([dataB1, dataB2, dataB3, dataB4, dataB5, dataB6, dataB7])
np.savetxt("stats.csv", np.stack((a,b)), delimiter=",", fmt='%s')
This error is coming:-
Traceback (most recent call last):
File "C:\Users\sbans\Documents\demo_opencv.py", line 32, in
np.savetxt("stats.csv", np.stack((a,b)), delimiter=",", fmt='%s')
File "<array_function internals>", line 6, in stack
File "C:\Users\sbans\AppData\Local\Programs\Python\Python37\lib\site-packages\numpy\core\shape_base.py", line 425, in stack
raise ValueError('all input arrays must have the same shape')
ValueError: all input arrays must have the same shape
You could simplify the code a bit by defining a function
def get_array(file):
img = cv.imread(file)
basename = os.path.basename(file)
height, width, channels = img.shape
h = int(height/2)
w = int(width/2)
px = img[h,w]
return np.array([basename, height, width, channels, px[0], px[1], px[2]])
Then savetxt can accept a list of same-sized 1D arrays
a = get_array('C:/Users/sbans/Pictures\bird.jpg')
b = get_array('C:/Users/sbans/Pictures\cat.jpg')
np.savetxt("stats.csv", (a, b), delimiter=",", fmt='%s')
The default behavior of np.savetxt method is to replace the existing file with a new data.
If you want to sequentially write the data to a file then you need to have a reference for that file then use it for np.savetxt.
For your case:
f = open('stats.csv','w')
...
np.savetxt(f, np.row_stack(np.column_stack((dataA1, dataA2, dataA3, dataA4, dataA5, dataA6, dataA7))), delimiter=",", fmt='%s')
...
np.savetxt(f, np.row_stack(np.column_stack((dataB1, dataB2, dataB3, dataB4, dataB5, dataB6, dataB7))), delimiter=",", fmt='%s')
f.close()
I'm currently trying to write a program that reads a GIF file and displays the inverse image on the screen. It is for a class, therefore I cannot download any additional add ons such as PIL. My original code included getting the size of the image and using those dimensions as the width and height, but when I did that I got an error on the line that says "inversePhoto = PhotoImage(width=500, height=250)", which is why I replaced "w" and "h" with the known dimensions of the image, for now. Since then I've received a new error:
Traceback (most recent call last):
File "C:/Users/Alexa/Documents/CS 299/InverseColors.py", line 31, in <module>
r,g,b = getRGB(photo, x, y)
File "C:/Users/Alexa/Documents/CS 299/InverseColors.py", line 13, in getRGB
value = photo.get(x, y)
File "C:\Python33\lib\tkinter\__init__.py", line 3438, in get
return self.tk.call(self.name, 'get', x, y)
_tkinter.TclError: pyimage1 get: coordinates out of range
I'm not quite sure what this error means...I'm assuming it has something to do x and y being either too small or too large for the image, but I'm not sure how that could be...here is my full code, I appreciate any help that can guide me in the right direction.
# InverseColors.py
# This program is designed to read a GIF file and display the inverse(negative) of its image
from tkinter import *
import struct
root = Tk()
def getRGB(photo, x, y):
value = photo.get(x, y)
return tuple(map(int, value.split(" ")))
def getImageSize(fileName):
handle = open(fileName, 'rb')
head = handle.read(24)
if len(head) != 24:
return
width, height = struct.unpack('>ii', head[16:24])
return width, height
def inverse(image, r, g, b, x, y):
image.put("#%02x%02x%02x" % ((255-r),(255-g),(255-b)), (y,x))
w, h = getImageSize("picture.gif")
photo = PhotoImage(file="picture.gif")
inversePhoto = PhotoImage(width=500, height=250)
for x in range(0,500):
for y in range(0,250):
r,g,b = getRGB(photo, x, y)
inverse(inversePhoto, r, g, b, x, y)
label = Label(root, image=inversePhoto)
label.grid()
root.mainloop()
I have a readfile.csv file have the struction as
E:\\Project_Face\\Projects\\arnold_schwarzenegger_01.jpg;1
E:\\Project_Face\\Projects\\arnold_schwarzenegger_02.jpg;1
E:\\Project_Face\\Projects\\emma_watson_01.jpg;0
I used the python to extract the path and lable (such as 0 and 1). Path and lable are separated by semicolon. I used a sample code to extract path of file ,rename it and save in other folder . The code is
CropFace(image, eye_left=(182,264), eye_right=(304,265), offset_pct=(0.1,0.1), dest_sz=(200,200)).save(".\\modified\\"+img.rstrip().split('\\')[5]+"_10_10_200_200.jpg")
However, I have the error
AttributeError: 'NoneType' object has no attribute 'save'
Note that the crop function returns the image type
Could you help me to fix it? Thank in advance. This is python code
import sys, math, Image
import os
def Distance(p1,p2):
dx = p2[0] - p1[0]
dy = p2[1] - p1[1]
return math.sqrt(dx*dx+dy*dy)
def ScaleRotateTranslate(image, angle, center = None, new_center = None, scale = None, resample=Image.BICUBIC):
if (scale is None) and (center is None):
return image.rotate(angle=angle, resample=resample)
nx,ny = x,y = center
sx=sy=1.0
if new_center:
(nx,ny) = new_center
if scale:
(sx,sy) = (scale, scale)
cosine = math.cos(angle)
sine = math.sin(angle)
a = cosine/sx
b = sine/sx
c = x-nx*a-ny*b
d = -sine/sy
e = cosine/sy
f = y-nx*d-ny*e
return image.transform(image.size, Image.AFFINE, (a,b,c,d,e,f), resample=resample)
def CropFace(image, eye_left=(0,0), eye_right=(0,0), offset_pct=(0.2,0.2), dest_sz = (70,70)):
# calculate offsets in original image
offset_h = math.floor(float(offset_pct[0])*dest_sz[0])
offset_v = math.floor(float(offset_pct[1])*dest_sz[1])
# get the direction
eye_direction = (eye_right[0] - eye_left[0], eye_right[1] - eye_left[1])
# calc rotation angle in radians
rotation = -math.atan2(float(eye_direction[1]),float(eye_direction[0]))
# distance between them
dist = Distance(eye_left, eye_right)
# calculate the reference eye-width
reference = dest_sz[0] - 2.0*offset_h
# scale factor
scale = float(dist)/float(reference)
# rotate original around the left eye
image = ScaleRotateTranslate(image, center=eye_left, angle=rotation)
# crop the rotated image
crop_xy = (eye_left[0] - scale*offset_h, eye_left[1] - scale*offset_v)
crop_size = (dest_sz[0]*scale, dest_sz[1]*scale)
image = image.crop((int(crop_xy[0]), int(crop_xy[1]), int(crop_xy[0]+crop_size[0]), int(crop_xy[1]+crop_size[1])))
# resize it
image = image.resize(dest_sz, Image.ANTIALIAS)
return image
def readFileNames():
try:
inFile = open('E:\\Project_Face\\Projects\\image_data.csv')
except:
raise IOError('There is no file named path_to_created_csv_file.csv in current directory.')
return False
picPath = []
picIndex = []
for line in inFile.readlines():
if line != '':
fields = line.rstrip().split(';')
picPath.append(fields[0])
picIndex.append(int(fields[1]))
return (picPath, picIndex)
if __name__ == "__main__":
[images, indexes]=readFileNames()
if not os.path.exists("modified"):
os.makedirs("modified")
for img in images:
image = Image.open(img)
CropFace(image, eye_left=(182,264), eye_right=(304,265), offset_pct=(0.1,0.1), dest_sz=(200,200)).save(".\\modified\\"+img.rstrip().split('\\')[5]+"_10_10_200_200.jpg")
CropFace(image, eye_left=(182,264), eye_right=(304,265), offset_pct=(0.2,0.2), dest_sz=(200,200)).save(".\\modified\\"+img.rstrip().split('\\')[5]+"_20_20_200_200.jpg")
CropFace(image, eye_left=(182,264), eye_right=(304,265), offset_pct=(0.3,0.3), dest_sz=(200,200)).save(".\\modified\\"+img.rstrip().split('\\')[5]+"_30_30_200_200.jpg")
CropFace(image, eye_left=(182,264), eye_right=(304,265), offset_pct=(0.2,0.2)).save("_20_20_70_70.jpg").save(".\\modified\\"+img.rstrip().split('\\')[5]+"_20_20_70_70.jpg")
Reread your last line, the one the error message points to:
CropFace(...).save(...).save(...)
save doesn't work like that. You probably only meant to have one of those save calls. If you meant to save it twice, store the return value of CropFace to a variable and use that to call save:
image = CropFace(...)
image.save(...)
image.save(other ...)
Next time, pay more attention to the error message. Also, show us the whole message, not just one line of it.