I had images that were in tiles of the following format:
Each number represents a single tile. I used the following script (with the help of stackoverflow) and stitched the images together. The following is the script that I used to stitch the images together:
from PIL import Image
import os
path_to_file ='tiff-files'
def stich_tile(path_to_file, xx , yy):
images = []
for i in os.listdir(path_to_file):
images.append(i)
if len(images) >= xx*yy:
pass
else:
raise ValueError('not enough images in path_to_file !!!!!!!!!!!')
sq_x = xx
sq_y = yy
img_x = (Image.open(path_to_file+'/'+images[0]).size[0])
img_y = (Image.open(path_to_file+'/'+images[0]).size[1])
img_mode = (Image.open(path_to_file+'/'+images[0]).mode)
new_image = Image.new(img_mode, (img_x*sq_x, img_y*sq_y))
x = 0
y = 0
cnt = 0
for i in images:
with Image.open(path_to_file+'/'+i) as img:
new_image.paste(img, (x,y))
cnt += 1
x += img_x
if cnt == sq_x:
x = 0
y += img_y
cnt = 0
else:
pass
return new_image
stich_tile(path_to_file, 3, 5).save('filename.tiff')
The output saved image looks like the following:
I would like to remove the black image that was created. How do I do that?
here modified script that removes black border from bottom and right of the stitched images... as long as the problem was within the starting images:
import numpy as np
from PIL import Image
import os
# path_to_file ='tiff-files'
# path_to_file ='tiff-files2'
# path_to_file ='tiff-files3'
# path_to_file ='tiff-files5'
# path_to_file ='tiff-files5'
path_to_file ='tiff-files6'
def stich_tile(path_to_file, xx , yy):
images = []
for i in os.listdir(path_to_file):
images.append(i)
images.sort() # sort images alphabetically
# images.sort(key = lambda x: int(x.strip('.tiff').split('-')[1])) ## ---> per path_to_file ='tiff-files3'
images = images[:xx*yy] #-----> riduce lista immagini al numero richiesto
print(images)
print('lenght list of images', len(images), 'x and y requested', xx*yy)
if len(images) >= xx*yy:
pass
else:
# raise ValueError('not enough images in path_to_file !!!!!!!!!!!')
raise ValueError('EXCEPTION not enough images in path_to_file !!!!!!!!!!!', xx*yy,'images needed : ', len(images),'images present !!!')
sq_x = xx
sq_y = yy
img_x = (Image.open(path_to_file+'/'+images[0]).size[0])
img_y = (Image.open(path_to_file+'/'+images[0]).size[1])
img_mode = (Image.open(path_to_file+'/'+images[0]).mode)
print('images[0] size : ', img_x, img_y, img_x*sq_x, img_y*sq_y)
new_image = Image.new(img_mode, (img_x*sq_x, img_y*sq_y))
print('new_image : size :', new_image.size)
x = 0
y = 0
cnt = 0
cnt_cycle = 0
for i in images:
with Image.open(path_to_file+'/'+i) as img:
new_image.paste(img, (x,y))
cnt += 1
cnt_cycle += 1
x += img_x
if cnt == sq_x:
x = 0
y += img_y
cnt = 0
else:
pass
print('count of for i in images cycles', cnt_cycle)
new_image = np.array(new_image)
print(new_image.shape, np.min(new_image), np.max(new_image))
for ar_y in range(new_image.shape[0]-1,0,-1):
res = np.all(new_image[ar_y,:] == (0,0,0))
if res:
new_image = new_image[0:(ar_y),:]
# print('black', ar_y)
else:
print('break at :', ar_y ,' row')
break
print(new_image.shape, np.min(new_image), np.max(new_image))
print(new_image.shape, np.min(new_image), np.max(new_image))
for ar_x in range(new_image.shape[1]-1,0,-1):
res = np.all(new_image[:,ar_x] == (0,0,0))
if res:
new_image = new_image[:,0:(ar_x)]
# print('black', ar_x)
else:
print('break at :', ar_x ,' column')
break
print(new_image.shape, np.min(new_image), np.max(new_image))
new_image = Image.fromarray(new_image)
return new_image
try :
pippo = stich_tile(path_to_file, 3,3)
pippo.show()
# pippo.save('RGB_black_tiff_3X.tiff')
except ValueError as err:
print('stopped', err.args)
could use same approach to remove black border from top/left.
Could be that pillow library has an in built option/function/whatever its called to do the same....
its kind of late here, tested code with 3X3 RGB tiff images with black borders.. let me know if it works
Related
I want to calculate variance, gabor and entropy filters to some images, but the images have blank areas that I donĀ“t want to apply the filters. I try to use a np.ma.array option but return this error: "'MaskedArray' object is not callable"
this is the code:
def bandas_img (image, array1, array2):
imagenRGB = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
return cv2.inRange(imagenRGB, array1, array2)
def rescale_by_width(image, target_width, method=cv2.INTER_LANCZOS4):
h = int(round(target_width * image.shape[0] / image.shape[1]))
return cv2.resize(image, (target_width, h), interpolation=method)
#Resized image by width
target_width = 400
#To mask null values
mask_image = True
hue = 20
sat = 57
value = 116
toleranciaH = 150
toleranciaS = 150
toleranciaV = 150
lower = np.array ([hue - toleranciaH, sat - toleranciaS, value - toleranciaV])
upper = np.array ([hue + toleranciaH, sat + toleranciaS, value + toleranciaV])
#working directory where the csv files are
os.chdir("C:/Users/Mariano/Documents/3 - Visual studio code/Prueba filtrar mascara/filtrada") ##ojoooo las barras van /// y no D:/OMAN/BHI TEXTURES/U-2
file_extension = '.png' #Check Extension
all_filenames = [i for i in glob.glob(f"*{file_extension}")]
for f in all_filenames:
image = cv2.imread(f,1)
#resized Image
resized1 = rescale_by_width(image, target_width)
#Set f value (image name)
f = f.replace(".png", "")
#Save Image
plt.imsave(f+"_resized.png", resized1)
#Create mask for null values
if mask_image == True:
mask = bandas_img(resized1, lower, upper)
cv2.imwrite(f+"_mask.png", mask)
resized2 = io.imread(f+"_resized.png", as_gray=True)
resized3 = resized2.copy()
#First Try
resized3[mask == 0] = np.nan
resized3[mask != 0] = resized2[mask != 0]
#Second Try
mask1 = (resized3 == np.nan)
resized_Mask = np.ma.array(resized3, mask = mask1)
#Varianza
k=6
img_mean = ndimage.uniform_filter(resized_Mask, (k, k))
img_sqr_mean = ndimage.uniform_filter(resized_Mask**2, (k, k))
img_var = img_sqr_mean - img_mean**2
img_var[mask == 0] = 1
plt.imsave(f+"_varianza.png", img_var)
i used this code below to extract patches from a image.
extract code:
import os
import glob
from PIL import Image
Image.MAX_IMAGE_PIXELS = None # to avoid image size warning
imgdir = "/path/to/image/folder"
filelist = [f for f in glob.glob(imgdir + "**/*.png", recursive=True)]
savedir = "/path/to/image/folder/output"
start_pos = start_x, start_y = (0, 0)
cropped_image_size = w, h = (256, 256)
for file in filelist:
img = Image.open(file)
width, height = img.size
frame_num = 1
for col_i in range(0, width, w):
for row_i in range(0, height, h):
crop = img.crop((col_i, row_i, col_i + w, row_i + h))
name = os.path.basename(file)
name = os.path.splitext(name)[0]
save_to= os.path.join(savedir, name+"_{:03}.png")
crop.save(save_to.format(frame_num))
frame_num += 1
Now i want to reconstruct this imagem from all those patches extracted before, i've tried 2 diffenret codes
so my DB is 120x256x256x3 extracted patches, theres 120 patches to fit in 3840x2048 shape..:
patches = []
for directory_path in glob.glob('D:\join_exemplo'):
for img_path in glob.glob(os.path.join(directory_path, "*.png")):
img = cv2.imread(img_path,1)
patches.append(img)
input_patches = np.array(patches)
first i've tried sklearn.feature_extraction.image importing reconstruct_from_patches_2d, but got a black image:
reconstruct = reconstruct_from_patches_2d(input_patches, input_image)
reconstruct = reconstruct.astype(np.uint8)
Image.fromarray(reconstruct, 'RGB').save(r'D:\join_exemplo\re\re3.png')
also tried, this below but got a grayscale tone pattern image
input_image = (3840,2048,3)
reconstructed_arr = np.zeros(shape=(3840,2048,3))
#%%
>>> step = 256
>>> for x in range(img.shape[0]):
for y in range(img.shape[1]):
x_pos, y_pos = x * step, y * step
reconstructed_arr[x_pos:x_pos + 512, y_pos:y_pos + 512] = img[x, y, 0, ...]
>>> (input_image == reconstructed_arr).all()
True
cv2.imwrite(r'D:\join_exemplo\re\re.png',reconstructed_arr)
Can someone see whats wrong? sorry about my bad english
I am using Yolov5. I want change my webcam -> lancamera
class LoadStreams: # multiple IP or RTSP cameras
def __init__(self, sources='streams.txt', img_size=640):
self.mode = 'images'
self.img_size = img_size
if os.path.isfile(sources):
with open(sources, 'r') as f:
sources = [x.strip() for x in f.read().splitlines() if len(x.strip())]
else:
sources = [sources]
n = len(sources)
self.imgs = [None] * n
self.sources = sources
for i, s in enumerate(sources):
# Start the thread to read frames from the video stream
print('%g/%g: %s... ' % (i + 1, n, s), end='')
cap = cv2.VideoCapture(eval(s) if s.isnumeric() else s)
assert cap.isOpened(), 'Failed to open %s' % s
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS) % 100
_, self.imgs[i] = cap.read() # guarantee first frame
thread = Thread(target=self.update, args=([i, cap]), daemon=True)
print(' success (%gx%g at %.2f FPS).' % (w, h, fps))
thread.start()
print('') # newline
# check for common shapes
s = np.stack([letterbox(x, new_shape=self.img_size)[0].shape for x in self.imgs], 0) # inference shapes
self.rect = np.unique(s, axis=0).shape[0] == 1 # rect inference if all shapes equal
if not self.rect:
print('WARNING: Different stream shapes detected. For optimal performance supply similarly-shaped streams.')
def update(self, index, cap):
# Read next stream frame in a daemon thread
n = 0
while cap.isOpened():
n += 1
# _, self.imgs[index] = cap.read()
cap.grab()
if n == 4: # read every 4th frame
_, self.imgs[index] = cap.retrieve()
n = 0
time.sleep(0.01) # wait time
def __iter__(self):
self.count = -1
return self
def __next__(self):
self.count += 1
img0 = self.imgs.copy()
if cv2.waitKey(1) == ord('q'): # q to quit
cv2.destroyAllWindows()
raise StopIteration
# Letterbox
img = [letterbox(x, new_shape=self.img_size, auto=self.rect)[0] for x in img0]
# Stack
img = np.stack(img, 0)
# Convert
img = img[:, :, :, ::-1].transpose(0, 3, 1, 2) # BGR to RGB, to bsx3x416x416
img = np.ascontiguousarray(img)
return self.sources, img, img0, None
def __len__(self):
return 0 # 1E12 frames = 32 streams at 30 FPS for 30 years
this code return 'self.sources, img, img0, None'
if webcam:
view_img = True
cudnn.benchmark = True # set True to speed up constant image size inference
dataset = LoadStreams(source, img_size=imgsz)
print((dataset))
I use 'dataset'
for path, img, im0s, vid_cap in dataset:
img = torch.from_numpy(img).to(device)
img = img.half() if half else img.float() # uint8 to fp16/32
img /= 255.0 # 0 - 255 to 0.0 - 1.0
How to use for path, img, im0s, vid_cap in dataset: ??
my lancam code
def livecame():
vimba = Vimba()
vimba.startup()
system = vimba.system()
system.run_feature_command("GeVDiscoveryAllOnce")
time.sleep(0.1)
camera_ids = vimba.camera_ids()
# for cam_id in camera_ids:
# print("Camera found: ", cam_id)
print(camera_ids[0])
c0 = vimba.camera(camera_ids[0])
c0.open()
pixel_format = c0.feature("PixelFormat")
pixel_format.value = "BayerBG8"
try:
c0.StreamBytesPerSecond = 100000000
except:
pass
frame = c0.new_frame()
frame.announce()
c0.start_capture()
try:
frame.queue_for_capture()
success = True
except:
success = False
c0.run_feature_command("AcquisitionStart")
c0.run_feature_command("AcquisitionStop")
frame.wait_for_capture(1000)
frame_data = frame.buffer_data()
k = cv2.waitKey(1)
if k == 0x1b:
cv2.destroyAllWindows()
if success:
img = np.ndarray(buffer=frame_data,
dtype=np.uint8,
shape=(frame.data.height, frame.data.width, 1))
img = cv2.cvtColor(img, cv2.COLOR_BAYER_BG2RGB)
img0 = img.copy()
img = img.tolist()
img = [letterbox(x, new_shape=(800,400), auto= True)[0] for x in img0]
#img = np.ascontiguousarray(img)
img = np.stack(img, 0)
#img = img[:, :, :, ::-1].transpose(0, 3, 1, 2) # BGR to RGB, to bsx3x416x416
img = np.ascontiguousarray(img)
return ['0'], img, img0
but I use dataset = new_file.livecame()
I can see error ValueError: not enough values to unpack (expected 3, got 1)
in for path, img, im0s, vid_cap in dataset:
how to use many variable? in for loop?
In Python OpenCV, one way is simply to use zip.
for component in zip(contours, hierarchy):
cntr = component[0]
hier = component[1]
I want to draw a box around an image where there are black pixels.
this is my image:(quiz.JPG):
and i would like the image to be something like this:
but with the code below I get this(quiz2.JPG):
here is what i have tried:
from PIL import Image,ImageDraw
image = Image.open("quiz.JPG").convert('L') #open and convert to black and white
pixels = image.load()
width, height = image.size
black_pixels= []
for col in range(width):
for row in range(height):
pixel = pixels[col, row]
if pixel == (0): #select pixels that are black
black_pixels.append((col, row)) #add them to the list of black pixels
def sortCoordinates(lst): #this is just a bubble sort to get the coordinates in order of y values
length = len(lst) -1
solved = False
while not solved:
solved = True
for i in range(length):
if lst[i][1] > lst[i+1][1]:
solved = False
lst[i],lst[i+1] = lst[i+1],lst[i]
return lst
black_pixels = sortCoordinates(black_pixels)
def getShape(black_pixels): # function to generate box from the pixels given
firstPixelXValue = black_pixels[0][0]
lastPixelXValue = black_pixels[-1][0]
tallestPixel = 0
for pixel in black_pixels:
YValue = pixel[1]
if YValue > tallestPixel:
tallestPixel = YValue
topMostPixelYValue = tallestPixel
shortestPixel = pixel[1]
for pixel in black_pixels:
YValue = pixel[1]
if YValue < shortestPixel:
shortestPixel = YValue
bottomMostPixelYValue = shortestPixel
shape = [(firstPixelXValue-4, topMostPixelYValue+2), (lastPixelXValue+4,bottomMostPixelYValue-3)]
return shape
questions = {}
count = 0
count2 = 0
currentQuestionPixels = []
oldPixelY = black_pixels[0][1]
for newPixel in black_pixels:
newPixelY = newPixel[1]
if newPixelY > oldPixelY + 100 or len(black_pixels)-1 == count2: #run this if new question is found
questions[str(count)] = getShape(currentQuestionPixels)
currentQuestionPixels = []
count += 1
oldPixelY = newPixelY
currentQuestionPixels.append(newPixel)
count2 += 1
image = image.convert('RGB')
for question in questions: #draw shape around all questions found
shape = questions.get(question)
img1 = ImageDraw.Draw(image)
img1.rectangle(shape, outline ="red")
image.save("quiz2.JPG")
This should work, in theory, because I am getting all the black pixel coordinates and sorting them out into their Y values. Then I am looping through the black pixels and if the new pixel Y value is grater than the old pixel Y value + 100 or it is the last pixel it must be a new question.
So then I draw a box around all the questions
I've modified the getShape function
Check out the code below
from PIL import Image,ImageDraw
image = Image.open("quiz.JPG").convert('L') #open and convert to black and white
pixels = image.load()
width, height = image.size
black_pixels= []
for col in range(width):
for row in range(height):
pixel = pixels[col, row]
if pixel == (0): #select pixels that are black
black_pixels.append((col, row)) #add them to the list of black pixels
def sortCoordinates(lst): #this is just a bubble sort to get the coordinates in order of y values
length = len(lst) -1
solved = False
while not solved:
solved = True
for i in range(length):
if lst[i][1] > lst[i+1][1]:
solved = False
lst[i],lst[i+1] = lst[i+1],lst[i]
return lst
black_pixels = sortCoordinates(black_pixels)
def getShape(black_pixels): # function to generate box from the pixels given
first_x = 0
first_y = 0
last_x = 99999999
last_y = 99999999
for x, y in black_pixels:
if first_x < x :
first_x = x
if first_y < y :
first_y = y
if last_x > x :
last_x = x
if last_y > y :
last_y = y
shape = [(first_x-4, first_y+2), (last_x+4,last_y-3)]
return shape
questions = {}
count = 0
count2 = 0
currentQuestionPixels = []
oldPixelY = black_pixels[0][1]
for newPixel in black_pixels:
newPixelY = newPixel[1]
if newPixelY > oldPixelY + 100 or len(black_pixels)-1 == count2: #run this if new question is found
questions[str(count)] = getShape(currentQuestionPixels)
currentQuestionPixels = []
count += 1
oldPixelY = newPixelY
currentQuestionPixels.append(newPixel)
# print(currentQuestionPixels)
count2 += 1
image = image.convert('RGB')
for question in questions: #draw shape around all questions found
shape = questions.get(question)
print(shape)
img1 = ImageDraw.Draw(image)
img1.rectangle(shape, outline ="red")
image.save("quiz2.JPG")
I am using a python script to stitch large images (10000 by 10000 pixels) together in a row. I can stitch the first six out of eight images together one at a time absolutely fine. However when I stitch more images beyond this point, I get 'Python.exe has stopped working'.
Code below:
from PIL import Image
import getopt, sys
args = sys.argv
ImageFileList = []
MasterWidth = 0
MasterHeight = 0
filename = ""
row = True
print """
Usage: python imageconnector.py [OPTIONS] [FILENAME] [FILE1] [FILE2] ...[FILE...]...
Combines [FILE1,2,...] into one file called [FILENAME]
OPTIONS:
-o <r/c> Stitch images into a row or a column. Default is row.
-c <colour> Change background fill colour. Default is black.
"""
def main(argv):
global args, MasterWidth, MasterHeight, ImageFileList, filename, deletename
try:
opts, args_files = getopt.getopt(argv, 'o:c:')
except getopt.GetoptError:
print "Illegal arguments!"
sys.exit(-1)
if '-o' in args:
index = args.index('-o')
cr = args[index + 1]
if cr == 'r':
row = True
elif cr == 'c':
row = False
else:
row = True
if '-c' in args:
index = args.index('-c')
colour = args[index + 1]
else:
colour = 'black'
filename = args_files.pop(0)
print('Combining the following images:')
if row:
for x in args_files:
try:
im = Image.open(x)
print(x)
MasterWidth += im.size[0]
if im.size[1] > MasterHeight:
MasterHeight = im.size[1]
else:
MasterHeight = MasterHeight
ImageFileList.append(x)
except:
raise
final_image = Image.new("RGB", (MasterWidth, MasterHeight), colour)
offset = 0
for x in ImageFileList:
temp_image = Image.open(x)
final_image.paste(temp_image, (offset, 0))
offset += temp_image.size[0]
final_image.save(filename)
else:
for x in args_files:
try:
im = Image.open(x)
print(x)
MasterHeight += im.size[1]
if im.size[0] > MasterWidth:
MasterWidth = im.size[0]
else:
MasterWidth = MasterWidth
ImageFileList.append(x)
except:
raise
final_image = Image.new("RGB", (MasterWidth, MasterHeight), colour)
offset = 0
for x in ImageFileList:
temp_image = Image.open(x)
final_image.paste(temp_image, (0, offset))
offset += temp_image.size[1]
final_image.save(filename)
if __name__ == "__main__":
try:
main(sys.argv[1:])
except IOError:
print 'One of more of the input image files is not valid.'
sys.exit(-1)
except SystemExit:
pass
except ValueError:
print 'Not a valid colour value.'
The answer was that Python Image Library (PIL) was 32 bit. I used the updated Pillow library (http://www.lfd.uci.edu/~gohlke/pythonlibs/thb9cnq7/Pillow-2.5.3.win-amd64-py2.7.exe) and it works perfectly. Uses a LOT of memory to stitch 60k pixel images though!