How to save multiple outputs after reading multiple inputs in Python - python

i am reading .png images from a folder and doing some operations and i want to save those images in an order like Img1.png, Img2.png, Img3.png.... i tried to use this code :
cv2.imwrite("Img{}.png".format(i),Image)
but it keeps overriding single image.
below is the code:
def main(path):
i=0
image = cv2.imread(path)
#do some operations on image
cv2.imwrite('Img{}.png'.format(i),image)
i=i+1
cv2.waitKey(0)
The path contains multiple .png images so when main executes it resets the value of 'i' and output is overridden.

I suppose it's because of the type of formatting. The old python uses '%s %s' % ('one', 'two')format, did you try this formatting?

I suppose that path - space separated:
path = "im1.png imre.png lena.jpg"
it seams so:
path_lst = path.split(' ')
for i, path_i in enumerate(path_lst):
image = cv2.imread(path_i)
#do some operations on image
cv2.imwrite('Img{}.png'.format(i),image)
all works. Idk - why they gave me "-" =D

Related

Replacing a word with another word, and replacing an image with another image in a PDF file through python, is this possible?

I need to replace a K words with K other words for every PDF file I have within a certain path file location and on top of this I need to replace every logo with another logo. I have around 1000 PDF files, and so I do not want to use Adobe Acrobat and edit 1 file at a time. How can I start this?
Replacing words seems at least doable as long as there is a decent PDF reader one can access through Python ( Note I want to do this task in Python ), however replacing an image might be more difficult. I will most likely have to find the dimension of the current image and resize the image being used to replace the current image dynamically, whilst the program runs through these PDF files.
Hi, so I've written down some code regarding this:
from pikepdf import Pdf, PdfImage, Name
import os
import glob
from PIL import Image
import zlib
example = Pdf.open(r'...\Likelihood.pdf')
PagesWithImages = []
ImageCodesForPages = []
# Grab all the pages and all the images in every page.
for i in example.pages:
if len(list(i.images.keys())) >= 1:
PagesWithImages.append(i)
ImageCodesForPages.append(list(i.images.keys()))
pdfImages = []
for i,j in zip(PagesWithImages, ImageCodesForPages):
for x in j:
pdfImages.append(i.images[x])
# Replace every single page using random image, ensure that the dimensions remain the same?
for i in pdfImages:
pdfimage = PdfImage(i)
rawimage = pdfimage.obj
im = Image.open(r'...\panda.jpg')
pillowimage = pdfimage.as_pil_image()
print(pillowimage.height)
print(pillowimage.width)
im = im.resize((pillowimage.width, pillowimage.height))
im.show()
rawimage.write(zlib.compress(im.tobytes()), filter=Name("/FlateDecode"))
rawimage.ColorSpace = Name("/DeviceRGB")
So just one problem, it doesn't actually replace anything. If you're wondering why and how I wrote this code I actually got it from this documentation:
https://buildmedia.readthedocs.org/media/pdf/pikepdf/latest/pikepdf.pdf
Start at Page 53
I essentially put all the pdfImages into a list, as 1 page can have multiple images. In conjunction with this, the last for loop essentially tries to replace all these images whilst maintaining the same width and height size. Also note, the file path names I changed here and it definitely is not the issue.
Again Thank You
I have figured out what I was doing wrong. So for anyone that wants to actually replace an image with another image in place on a PDF file what you do is:
from pikepdf import Pdf, PdfImage, Name
from PIL import Image
import zlib
example = Pdf.open(filepath, allow_overwriting_input=True)
PagesWithImages = []
ImageCodesForPages = []
# Grab all the pages and all the images in every page.
for i in example.pages:
imagelists = list(i.images.keys())
if len(imagelists) >= 1:
for x in imagelists:
rawimage = i.images[x]
pdfimage = PdfImage(rawimage)
rawimage = pdfimage.obj
pillowimage = pdfimage.as_pil_image()
im = Image.open(imagePath)
im = im.resize((pillowimage.width, pillowimage.height))
rawimage.write(zlib.compress(im.tobytes()), filter=Name("/FlateDecode"))
rawimage.ColorSpace = Name("/DeviceRGB")
rawimage.Width, rawimage.Height = pillowimage.width, pillowimage.height
example.save()
Essentially, I changed the arguements in the first line, such that I specify that I can overwrite. In conjunction, I also added the last line which actually allows me to save.

Python/Opencv save multiple images to folder with different names

I am working on image processing, I have a folder with all of the images that needs to be processed, and I want to save all the processed images to another folder. How do I do that?
for img in glob.glob("Img/*.png"):
path = '/result'
image = cv2.imread(img)
angle, rotated = correct_skew(image)
print(angle)
cv2.imwrite(os.path.join(path , 'img.png'), rotated)
cv2.waitKey(1)
This code can read the image and process it, but I can't figure out how to save all the images with different names, like I want it to be img1.png, img2.png, etc.
Or is there anyway that I can save the images to another folder with the same names as before?
In order to save your processed images in a serial manner, you can use enumerate. When a loop is initiated using enumerate, a counter is also initiated. And each iteration yields an integer number.
In the following case i is the integer value which increments for each iteration. i is used as part of the file name to save the processed image
path = '/result'
for i, img in enumerate(glob.glob("Img/*.png"), 1):
image = cv2.imread(img)
angle, rotated = correct_skew(image)
print(angle)
cv2.imwrite(os.path.join(output_path, 'img_{}.png'.format(i)), rotated)
Save the last line as a variable wrapped in a string()
Then cv2.imwrite(variable)for the last line.
#My thought is to change the type to a string and then write the file as originally desired. When you save as a string you can change whatever type it is turning into inside the for statement.

How to utilise ffmpeg to to extract key frames from a video stream and only print the labels present within these frames?

So a bit of context, I'm using the TensorFlow object detection API for a project, and I've modified the visualization_utils file to print any present class labels to the terminal and then write them to a .txt file. From a bit of research I've come across FFmpeg, I'm wondering if there is a function I can use in FFmpeg so that it only prints and writes the class labels from keyframes within the video? - i.e. when there is a change in the video. At the moment it is printing all the class labels per frame even if there is no change, so I have duplicate numbers of labels even if there is no new object within the video. Following on from this, would I have to apply this keyframe filtering to an input video beforehand?
Thanks in advance!
I'm using opencv2 to capture my video input.
Please see below for code:
visualization_utils.py - inside the draw_bounding_box_on_image_array function:
# Write video output to file for evaluation.
f = open("ObjDecOutput.txt", "a")
print(display_str_list[0])
f.write(display_str_list[0])
Thought I'd just follow up on this, I ended up using ffmpeg mpdecimate and setpts filters to remove duplicate and similar frames.
ffmpeg -i example.mp4 -vf mpdecimate=frac=1,setpts=N/FRAME_RATE/TB example_decimated.mp4
This however didn't solve the problem of duplicates within the file I was writing the labels to - to solve this I appended each row in the file to a list and looped through it to remove groups of duplicated elements and only kept the first occurrence and appended that to a new list.
Finally, I found the solution here after a year. However, there is a small bug in the code converted from this script.
The fix is and frame["key_frame"]
import json
import subprocess
def get_frames_metadata(file):
command = '"{ffexec}" -show_frames -print_format json "{filename}"'.format(ffexec='ffprobe', filename=file)
response_json = subprocess.check_output(command, shell=True, stderr=None)
frames = json.loads(response_json)["frames"]
frames_metadata, frames_type, frames_type_bool = [], [], []
for frame in frames:
if frame["media_type"] == "video":
video_frame = json.dumps(dict(frame), indent=4)
frames_metadata.append(video_frame)
frames_type.append(frame["pict_type"])
if frame["pict_type"] == "I" and frame["key_frame"]:
frames_type_bool.append(True)
else:
frames_type_bool.append(False)
# print(frames_type)
return frames_metadata, frames_type, frames_type_bool
The frame types are stores in frames_type, but don't trust it. True keyframes are in frames_type_bool.
I tested a clip for which I had two consecutive I-frames at the beginning, but avidemux was showing only one. So I checked the original code and found that some frames may have pict_type = I but key_frame = False. I thus fixed the code.
After having the frames_type_bool, you can extract the True indices and opencv or imageio to extract keyframes only.
This is how to use this function and imageio to show the keyframes:
import matplotlib.pyplot as plt
import imageio
filename = 'Clip.mp4'
# extract frame types
_,_, isKeyFrame = get_frames_metadata(filename)
# keep keyframes indices
keyframes_index = [i for i,b in enumerate(isKeyFrame) if b]
# open file
vid = imageio.get_reader(filename, 'ffmpeg')
for i in keyframes_index:
image = vid.get_data(i)
fig = plt.figure()
fig.suptitle('image #{}'.format(i), fontsize=20)
plt.imshow(image)
plt.show()

Avoid extracting repeat images from PDF

I'm attempting to use Optical Character Recognition on scanned image pdfs in python. This requires extracting the images within the text, and this is where I've run into issues. Some of the PDFs I'm extracting from have a ~header image on every page that gets extracted once per page. Is there a way to avoid this? I'm primarily trying to reduce the number of images I have to feed into my OCR algorithm.
Currently I do image extraction with the following two methods, though I'm ok with using a different method (though I've had multiple hours of difficulty just trying to install textract and haven't gotten it so far, so maybe not that package).
Method 1: Poppler's pdfimages tool via command line via os
def image_exporter(pdf_path, output_dir):
if not os.path.exists(output_dir):
os.makedirs(output_dir)
cmd = ['pdfimages', '-png', '-p', pdf_path,
'{}/prefix'.format(output_dir)]
subprocess.call(cmd)
print('Images extracted')
Method 2: Fitz/PyMuPDF
def img_extract(pdf_path, output_dir):
name_start = pdf_path.split('\\')[-1][:15]
doc = fitz.open(pdf_path)
for i in range(len(doc)):
for img in doc.getPageImageList(i):
xref = img[0]
pix = fitz.Pixmap(doc, xref)
name = "p%s-%s.png" % (i, xref)
name = name_start + ' ' + name
name = output_dir + '\\' + name
if pix.n < 5: # this is GRAY or RGB
#pix.writePNG(name)
pix.writeImage(name)
else: # CMYK: convert to RGB first
pix1 = fitz.Pixmap(fitz.csRGB, pix)
#pix1.writePNG(name)
pix1.writeImage(name)
pix1 = None
pix = None
Both of these are essentially copies of code I found elsewhere (Extract images from PDF without resampling, in python? being one of the sources).
I should also mention that I have very little understanding of the structure of a pdf document itself. So I'm having other odd things happening (extracting inversed color images, super blurred images, image1 of pg_x where its got text with random letters missing & image2 of same pg_x with the random missing letters but none of the letters in image1, etc). So perhaps an equally valid question is if there is a way to combine all the images on one page into a single image that I can scan with my OCR code? I'm primarily trying to avoid having to scan through huge quantities of images.

Applying filter to every photo in directory

I am new to python, so go easy on me! I am trying to apply a blur to every .bmp image in a folder. I am able to get the first half of the code to work, so the filter is applied to all the photos, but then I can't get it to re-save each image. I want to keep the original images, and add the new images to the folder. Here's what I have:
from PIL import Image from PIL import ImageFilter import os, fileinput, sys
##for every item in X folder that ends in X, apply a basic blur to the image##
for entry in os.scandir('/Users/kh'):
if entry.path.endswith('.bmp'):
img = Image.open(entry.path)
img = img.filter(ImageFilter.BoxBlur(2))
img.show()
##and then re-save each of those new images under a new filename##
# Split our original filename into name and extension
(name, extension) = os.path.splitext(filepath)
# Save with "_blur" added to the filename
img.save(name + '_blur' + extension)
# Save the image as a BMP
img.save(name + '.bmp')
I've tried a bunch of other stuff, but this code is the closest I've gotten. Thanks so much for your help.
I tried your code. I actually get:
NameError: name 'filepath' is not defined
because you have a filepath which should be entry.path:
(name, extension) = os.path.splitext(entry.path)
Besides this, your code works, except that you have both images blurred. The last line:
img.save(name + '.bmp')
is cleary not needed, it overwrites the original images with the blurred ones.

Categories

Resources