I use opencv to count the number of white and black pixels of picture(I have convert them into black and white image), and everytime I run my code it return the number is 0,and the code is
output_path = "/content/drive/MyDrive/dataset_demo/result_pic"
for pic in os.listdir(output_path):
if pic.endswith('.jpg'):
image = cv2.imread(pic,cv2.IMREAD_UNCHANGED)
number_of_white_pix = np.sum(image == 255)
number_of_black_pix = np.sum(image == 0)
number_of_total = number_of_white_pix + number_of_black_pix
number_of_ratio = number_of_white_pix / number_of_black_pix
print(number_of_total)
The pic variable contains only the file name of the image, but cv2.imread needs the full path to the image in order to read it. You need to use the full path to the image when you call cv2.imread.
output_path = "/content/drive/MyDrive/dataset_demo/result_pic"
for pic in os.listdir(output_path):
if pic.endswith('.jpg'):
pic = os.path.join(output_path, pic) #full path to the image
image = cv2.imread(pic,cv2.IMREAD_UNCHANGED)
number_of_white_pix = np.sum(image == 255)
number_of_black_pix = np.sum(image == 0)
number_of_total = number_of_white_pix + number_of_black_pix
number_of_ratio = number_of_white_pix / number_of_black_pix
print(number_of_total)
Related
I'm trying to write a program in Python that takes an image and replaces the pixels with images, based off of the pixels lightness value. Figured I'd start with following a tutorial on converting images to ASCII art, then I can replace the ASCII characters with images. Here's what this attempt looks like:
https://pastebin.com/VNFWd9xN
It's a bit quick and dirty, just to see if I can make it work, but I think you'll get the idea.
So, a couple of issues I ran into.
The first and biggest one, i get a "TypeError: sequence item 0: expected str instance, JpegImageFile found". I get that the program expects a string and gets an image instead. But, how do I solve that?
Lastly, more of a parenthesis really, but I was playing around with the save function and could not get it so save "ascii_image" to jpg.
Anyhow, would really appreciate some guidance here.
Thank you.
import PIL.Image
from PIL import Image
img1 = Image.open("image1.jpg")
img2 = Image.open("image2.jpg")
img3 = Image.open("image3.jpg")
img4 = Image.open("image4.jpg")
img5 = Image.open("image5.jpg")
img6 = Image.open("image6.jpg")
img7 = Image.open("image7.jpg")
img8 = Image.open("image8.jpg")
img9 = Image.open("image9.jpg")
img10 = Image.open("image10.jpg")
img11 = Image.open("image11.jpg")
img12 = Image.open("image12.jpg")
# ascii characters used to build the output text
#ASCII_CHARS = ["#", "#", "S", "%", "?", "*", "+", ";", ":", ",", "."]
ASCII_CHARS = [img1, img2, img3, img4, img5, img6, img8, img9, img10, img11, img12]
# resize image according to a new width
def resize_image(image, new_width=80):
width, height = image.size
ratio = height/width
new_height = int(new_width * ratio)
resized_image = image.resize((new_width, new_height))
return(resized_image)
# convert each pixel to greyscale
def grayify(image):
grayscale_image = image.convert("L")
return(grayscale_image)
# convert pixels to a string of ASCII characters
def pixels_to_ascii(image):
pixels = image.getdata()
characters = "".join([ASCII_CHARS[pixel//25] for pixel in pixels])
return(characters)
def main(new_width=80):
# attempt to open image from user-input
path = input("Enter path to image:\n")
try:
image = PIL.Image.open(path)
except:
print(path, " is not a valid pathname to an image")
return
# convert image to ASCII
new_image_data = pixels_to_ascii(grayify(resize_image(image)))
# format
pixel_count = len(new_image_data)
ascii_image = "\n".join([new_image_data[index:(index+new_width)] for index in range(0, pixel_count, new_width)])
# print result
print(ascii_image)
# save
#with Image.open("ascii_image.jpg") as f:
# f.write(ascii_image)
main()
Why does image.getdata() return different result second time I invoke it?
from PIL import Image
def write():
image = Image.open('image.jpg')
newimage = Image.new(image.mode, image.size)
pixels = [p for p in image.getdata()]
for i in range(100):
pixels[i] = (255,255,255)
newimage.putdata(pixels)
newimage.save('newimage.jpg')
print(list(newimage.getdata())[0:10])
def read():
image = Image.open('newimage.jpg')
pixels = [p for p in image.getdata()]
print(list(image.getdata())[0:10])
write()
read()
It gives me the following result:
Why is second set of data differ from the first one?
I've read another thread on SO regarding image rotation here:
PIL thumbnail is rotating my image?
and I've read another thread on SO about EXIF preservation here:
Preserve exif data of image with PIL when resize(create thumbnail)
Unfortunately, after implementing the suggestions above, it seems that I can only have either:
1) a saved rotated image without EXIF data
or
2) a non-rotated image with EXIF data
but it seems that I can't have both.
I'm hoping I can get some help to fix what I thought was a real simple problem, but has been turning into a scream-fest against my computer for the past few hours.
Here's the relevant parts of my code:
from PIL import Image, ExifTags
import piexif
currImage = Image.open(inFileName)
exif_dict = piexif.load(currImage.info["exif"])
for orientation in ExifTags.TAGS.keys():
if ExifTags.TAGS[orientation]=='Orientation':
break
exif=dict(currImage._getexif().items())
if exif[orientation] == 3:
currImage=currImage.rotate(180, expand=True)
elif exif[orientation] == 6:
currImage=currImage.rotate(270, expand=True)
elif exif[orientation] == 8:
currImage=currImage.rotate(90, expand=True)
currWidth, currHeight = currImage.size
# Here is where I can only do one or the other. Don't know enough about how to get both
exif_bytes = piexif.dump(exif_dict)
#exif_bytes = piexif.dump(exif)
maxImageDimension = [1280, 640, 360, 160]
for imgDim in maxImageDimension:
thumbRatio = imgDim / max(currWidth, currHeight)
# note that because Python's round function is mathematically incorrect, I have to do the following workaround
newWidth = int(Decimal(str(thumbRatio * currWidth)).quantize(Decimal('0.'), rounding=ROUND_UP))
newHeight = int(Decimal(str(thumbRatio * currHeight)).quantize(Decimal('0.'), rounding=ROUND_UP))
# copy currImage object
newImage = currImage
# note that I have to do resize method because thumbnail method has same rounding problem
newImage = newImage.resize((newWidth, newHeight))
# save the thumbnail
if imgDim == 1280:
outFileName = destinationDir + '\\' + file[:len(file)-4] + '.jpg'
else:
outFileName = destinationDir + '\\' + file[:len(file)-4] + '-' + str(newWidth) + 'x' + str(newHeight) + '.jpg'
print('Writing: ' + outFileName)
# Here is where I have to choose between exif or exif_bytes when saving but I can only get one or the other desired result
newImage.save(outFileName, exif=exif_bytes)
print('\n')
currImage.close()
newImage.close()
Thanks in advance.
I have two folders of images and I am trying to build one large image from all the slices in each folder. I need to alternate between folders to build the image. For example the first slice comes from folder 1, the second slice comes from folder 2, the third from folder 1 ect. I have the files ordered by filename in the individual folders so I am trying to iterate through the folders and add a new strip to an image. The code runs BUT it doesn't seem to be saving the composite image. I am new to PIL, so I am sure that it is something simple, but your help is appreciated. Thanks!
def merge_images(file1, file2):
"""Merge two images into one, displayed above and below
:param file1: path to first image file
:param file2: path to second image file
:return: the merged Image object
"""
if file1.startswith('.'):
return None
image1 = Image.open(file1)
image2 = Image.open(file2)
(width1, height1) = image1.size
(width2, height2) = image2.size
result_width = width1 + width2
result_height = max(height1, height2)
result = Image.new('RGB', (result_width, result_height))
result.paste(im=image1, box=(0, 0))
result.paste(im=image2, box=(0, height1))
return result
imageCounter = 0
firstPass = True
compImage = Image.new('RGBA', img.size, (0,0,0,0))
for i in range(len(boundingBoxes)+1):
if firstPass:
compImage = merge_images('./image_processing/'+ os.listdir('./image_processing/')[imageCounter],
'./img_patches/outputs/'+os.listdir('./img_patches/outputs/')[imageCounter])
if compImage is not None:
firstPass = False
compImage.save('./image_processing/compImage.jpg')
else:
compImage = merge_images('./image_processing/compImage.jpg','./image_processing/'+ os.listdir('./image_processing/')[imageCounter])
compImage.save('./image_processing/compImage.jpg')
compImage = merge_images('./image_processing/compImage.jpg','./img_patches/outputs/'+ os.listdir('./img_patches/outputs/')[imageCounter])
compImage.save('./image_processing/compImage.jpg')
imageCounter = imageCounter + 1
You have to tell PIL to save the images:
for i in range(len(boundingBoxes)+1):
if firstPass:
compImage = merge_images('./image_processing/'+ os.listdir('./image_processing/')[imageCounter],
'./img_patches/outputs/'+os.listdir('./img_patches/outputs/')[imageCounter])
compImage.save(open('output/{}.png'.format(imageCounter), 'w'))
I am fairly new to Python and have a difficult Problem to solve:
Here is what I am trying to do -->
I have a Folder (path known) with 1 - x picture files (.jpg) in it, whereas x can be as high as 1000
These picture files should be stiched together (one on top of the other)
To do so I want Python to assign a variable to each Picture file in the known folder and then create a loop which stiches these variable-stored pictures together and outputs it as 1 picture (.jpg)
Here is what I have coded so far:
from PIL import Image
import glob
#The following GLOB part doesn't work, I tried to make a List with all the
#files (.jpg) inside the main directory
#image_list = []
#for filename in glob.glob('*.jpg'):
# test = Image.open(filename)
# image_list.append(test)
img1 = Image.open("img1.jpg")
img2 = Image.open("img2.jpg")
def merge_images(img1, img2):
(width1, height1) = img1.size
(width2, height2) = img2.size
result_width = max(width1, width2)
result_height = height1 + height2
result = Image.new('RGB', (result_width, result_height))
result.paste(im=img2, box=(0,0))
result.paste(im=img1, box=(0,height1-2890))
return result
merged = merge_images(img1, img2)
merged.save("test.jpg")
What this does is to assign img1.jpg and img2.jpg to a variable and then stack them on top of oneanother and save this stacked picture as "test.jpg". Where do I go from here if I want to assign many pictures (.jpg) to variables and stack them on top of each other without typing a line of code for each new picture (see description further up?)
Thanks a lot for your help!
Chris
If you start with a 0x0 image, you can stack further images onto it like this:
stacked_img = Image.new('RGB', (0, 0))
for filename in glob.glob('*.jpg'):
stacked_img = merge_images(stacked_img, Image.open(filename))
stacked_img.save('stacked.jpg')
You might also like to change the height1-2890 to height2 in the merge_images() function if you are trying to stack the second image below the first image, i.e.
result.paste(im=img1, box=(0,height2))
Why not use a container such as a list?
images = [Image.open(img_name) for img_name in os.listdir(my_folder) if img_name.endswith('.jpg')
def merge_images(list_images):
result_width = max(img.size[0] for img in images)
result_height = sum(img.size[1] for img in images)
result = Image.new('RGB', (result_width, result_height))
for idx, img in enumerate(list_images):
result.paste(im=img, box=(0,list_images[0].size[1]-idx*2890))
See Data Structures for more information.
If performance is important, consider using map instead of a loop.
this is my code in which I implemented your approach. As a result, I am getting an image where 2 of the 4 images are displayed and the rest of the image is black. In the source directory I have 4 images (img1.jpg - img4.jpg)
from PIL import Image
import glob
stacked_img = Image.new('RGB', (0,0))
def merge_images(img1, img2):
(width1, height1) = img1.size
(width2, height2) = img2.size
result_width = max(width1, width2)
result_height = height1 + height2
result = Image.new('RGB', (result_width, result_height))
result.paste(im=img2, box=(0,0))
result.paste(im=img1, box=(0,height1))
return result
for filename in glob.glob('*.jpg'):
stacked_img = merge_images(stacked_img, Image.open(filename))
stacked_img.save('stacked.jpg')