ffmpeg lossless conversion from jpgs to video with huffyuv not working as expected - opencv

I'm trying to create a video from a set of jpg images. I would like that each frame of the video is exactly the same of the images used to create it. In order to get this result I'm using the following command:
ffmpeg -i %05d.jpg -c:v huffyuv test.avi
However if I check if the first frame is equal to the first image used to create the video I get some differences. In order to check this I used the following code:
import argparse
import cv2
import glob
import os
from os.path import isfile, join
parser = argparse.ArgumentParser()
parser.add_argument(
"video",
default = None,
help = 'video to be compared',
type = str)
parser.add_argument(
"image",
default = None,
help = 'image to be compared with the first frame of the video',
type = str)
args = parser.parse_args()
# opening video
cap = cv2.VideoCapture(args.video)
# reading first frame
ret, frame = cap.read()
# opening image
image = cv2.imread(args.image)
# computing difference between the first frame of the video and the image
diff = frame - image
# showing the differences: the two images are equal if the result is a black image
cv2.imshow("diff", diff)
cv2.waitKey(0)
cv2.destroyAllWindows()
If I use opencv to perform the conversion the result is as expected: no differences between the first frame and the first image used to create the video. This is python code used to generate the video from the images:
import argparse
import cv2
import glob
import os
parser = argparse.ArgumentParser()
parser.add_argument(
"jpg_folder",
default = None,
help = 'Path to folder with numbered jpg folder, must be alphabetically ordered (e.g 00000.jpg, 00001.jpg, ...)',
type = str)
parser.add_argument(
"avi_output",
default = None,
help = 'name of the outputavi file',
type = str)
parser.add_argument(
"--frame-rate",
default = 30,
help = 'number of frame per second used in the genrerated video (default is 30)',
type = int)
args = parser.parse_args()
#read images to be used to create the video
files = glob.glob(os.path.join(args.jpg_folder,'*.jpg'))
files.sort(key=lambda x: x)
#extract images dimensions
tmp_img = cv2.imread(files[0])
height, width, layers = tmp_img.shape
#create video writer with lossless codec
out = cv2.VideoWriter(args.avi_output,cv2.VideoWriter_fourcc('H', 'F', 'Y', 'U'), args.frame_rate, (width, height))
#read each image and add it to the video
for filename in files:
jpgImage = cv2.imread(filename)
out.write(jpgImage)
#release the resource used to write the video
out.release()
Am I missing some option in order to get the same result using ffmpeg?

Related

How to decrease the speed of Video using cv2.VideoWriter()?

I'm trying to write a video using cv2.VideoWriter() and I defined the following function.
the point is that when I change the fps=30 to 20 or any other value, there is no change in the output and the video play speed is higher than what I would like to have.
def video_Writer(images_path_read, output_vid_path, fps=30):
'''
parameters:
- images_path_read - the path containing images to be combined and make a video
- output_vid_path - the path and file name of output video (must include .mp4)
method:
- the function get the images path, read the sorted images and make a video according
to the first image size.
'''
dir_images_list = os.listdir(images_path_read)
dir_images_list = natsorted(dir_images_list)
# get the size of the first image
fourcc = VideoWriter_fourcc(*'mp4v')
img_0 = cv2.imread(images_path_read + dir_images_list[0])
# find the image shape
size = (img_0.shape[1], img_0.shape[0])
# Creating VideoWriter Object and open it to start in the loop
vid_writer = cv2.VideoWriter(output_vid_path, fourcc, fps, size)
vid_writer.open(output_vid_path, fourcc, fps, size)
for image in dir_images_list:
# Reading the images from the path folder
img = cv2.imread(images_path_read + image)
# Checking the size of frames
if size[0] != img.shape[1] or size[1] != img.shape[0]:
img = resize(img, size)
print('Resizing Happend')
# Adding images to Video
vid_writer.write(img)
# print(image)
# Releasing VideoWriter Object
vid_writer.release()
Please help me to find out the reason.
Thanks

Resize a small image to get the text from it using python

I'm new to image processing libraries in python, currently i'm failing trying to get a text from a small image 147x15 with a transparent background. One way to perform that is to resize the image by making it bigger and trying not to loose quality so it can be well interpreted, there is the original image link:
(147x15)
https://www.lespagesmaghreb.com/generated/contact_methods/496321.png
This is my code to get the text from the image:
import cv2
import pytesseract
from PIL import Image
pytesseract.pytesseract.tesseract_cmd = r'C:\\Program Files\\Tesseract-OCR\\tesseract.exe'
img = cv2.imread('img_new.png')
text = pytesseract.image_to_string(img)
print(text)
And there is the expected image (181 x 80) output which works with the previous code (manually edited)
How can I perform that automatically ? thanks.
EDIT:
I tried to resize the image to 200% of it's current size, the result is a black image, this is the used code:
import cv2
img = cv2.imread('img_n.png', cv2.IMREAD_UNCHANGED)
print('Original Dimensions : ',img.shape)
scale_percent = 200 # percent of original size
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent / 100)
dim = (width, height)
# resize image
resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
print('Resized Dimensions : ',resized.shape)
cv2.imshow("Resized image", resized)
cv2.waitKey(0)
cv2.destroyAllWindows()
This is the image:

how to stack image files in to one file and how to resize black and white images

here my images look like this enter image description here
I am trying to stack the images files into one file and also resizing black white images 1000X1000. But I didn't get, I have images with size 600X400, but I need it's to 1000 pixels size, please help me how to do.
Here my images loading:
import cv2
import glob
img= [cv2.imread(file) for file in glob.glob('C:/Users/NanduCn/jupter1/deepl/challenges-master/ML/stack1/*jpg')]
img2= [cv2.imread(file) for file in glob.glob('C:/Users/NanduCn/jupter1/deepl/challenges-master/ML/stack2/*jpg')]
img3= [cv2.imread(file) for file in glob.glob('C:/Users/NanduCn/jupter1/deepl/challenges-master/ML/stack3/*jpg')]
img4= [cv2.imread(file) for file in glob.glob('C:/Users/NanduCn/jupter1/deepl/challenges-master/ML/stack4/*jpg')]
here I am taking all images into one list:
img=img1+img2+img3+img4
Here my resize the images :
im_g=cv2.resize(img,(1000,1000))
--------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-69-56a6794f0ec5> in <module>()
----> 1 im_g=cv2.resize(img,(1000,1000))
TypeError: src is not a numpy array, neither a scalar
In your code, img1, img2, img3, img4 are lists. When you use the + operator, they are stacked in the list way.
For example, N images with size (h,w) in each folder (stack1, stack2, ...), the shape of img1 is (N, h, w). However, the shape of img1+img2 is (2N, h, w). Use numpy array instead.
import cv2
import glob
import numpy as np
img1 = np.array([cv2.imread(file) for file in glob.glob('C:/Users/NanduCn/jupter1/deepl/challenges-master/ML/stack1/*jpg')])
img2 = np.array([cv2.imread(file) for file in glob.glob('C:/Users/NanduCn/jupter1/deepl/challenges-master/ML/stack2/*jpg')])
img3 = np.array([cv2.imread(file) for file in glob.glob('C:/Users/NanduCn/jupter1/deepl/challenges-master/ML/stack3/*jpg')])
img4 = np.array([cv2.imread(file) for file in glob.glob('C:/Users/NanduCn/jupter1/deepl/challenges-master/ML/stack4/*jpg')])
imgs = list(img1+img2+img3+img4)
for img in imgs:
im_g = cv2.resize(img,(1000,1000))
How many files are there in the folder (stack1, stack2, ...)?
In your way of using glob, the result will be multiple files. You have to add one more step that stack files in the folder.
If the desired result is only one file, try this.
import cv2
import glob
import numpy as np
img1 = [cv2.imread(file) for file in glob.glob('C:/Users/NanduCn/jupter1/deepl/challenges-master/ML/stack1/*jpg')]
img2 = [cv2.imread(file) for file in glob.glob('C:/Users/NanduCn/jupter1/deepl/challenges-master/ML/stack2/*jpg')]
img3 = [cv2.imread(file) for file in glob.glob('C:/Users/NanduCn/jupter1/deepl/challenges-master/ML/stack3/*jpg')]
img4 = [cv2.imread(file) for file in glob.glob('C:/Users/NanduCn/jupter1/deepl/challenges-master/ML/stack4/*jpg')]
imgs = (img1+img2+img3+img4)
stacked_img = np.array(img1[0])
for img in imgs[1:]:
stacked_img += np.array(img)
im_g = cv2.resize(stacked_img,(1000,1000))
Note: you may want to normalize(average) the value of the stacked image.

How to import and use scipy.spatial.distance functions correctly?

from scipy.spatial.distance import seuclidean #imports abridged
import scipy
img = np.asarray(Image.open("testtwo.tif").convert('L'))
img = 1 * (img < 127)
area = (img == 0).sum() # computing white pixel area
print area
areasplit = np.split(img, 24) # splitting image array
print areasplit
for i in areasplit:
result = (i == 0).sum()
print result #computing white pixel area for every single array
minimal = result.min()
maximal = result.max()
dist = seuclidian(minimal, maximal)
print dist
I want to compute distances between array elements, produced from splitting an image. Python can`t recognize the name of a distance functions (I have tried several of them and variuos approaches to importing modules). How to import and call these functions correctly? Thank you
You haven't stated what the error is, but you are using numpy as well and I can't see an import for that
Try
import numpy as np
import scipy
Then try
dist = scipy.spatial.distance.euclidian(minimal, maximal)
dists = scipy.spatial.distance.seuclidian(minimal, maximal, variances)
Note - the standardised euclidean distance takes a third parameter.

Converting numpy array having image data to CvMat

I have an image in a numpy array which I save using savefig and then use opencv loadImage function to load the image to a CvMat. But I want to remove this saving the image step.
My Numpy Image size is 25x21, and if I use fromArray function like
im = cv.fromarray(asarray(img))
I get a CvMat of size 25x21 which is very small. But When I save the image to png format and load it back using LoadImage, I get the full sized image of size 429x509.
Can somebody please tell me how do I get this full sized image from numpy array to CvMat? Can I convert the image from numpy array to a png format in code without saving it using savefig()?
This is what I am doing right now.
imgFigure = imshow(zeros((gridM,gridN)),cmap=cm.gray,vmin=VMIN,vmax=5,animated=True,interpolation='nearest',extent=[xmin,xmax,ymin,ymax])
imgFigure.set_data(reshape(img,(gridM,gridN)))
draw()
fileName = '1p_'
fileName += str(counter)
fileName += ".png"
savefig(fileName,bbox_inches='tight',pad_inches=0.01,facecolor='black')
The size of img above is 525 and gridM and gridN are 25 and 21.Then I load this image using:
img = cv.LoadImage(fileName, cv.CV_LOAD_IMAGE_GRAYSCALE)
Now img size is 429x509.
You can just use cv.fromarray() directly upon your numpy array with no need to save inbetween:
import cv
import numpy as np
a = np.arange(0,255,0.0255).reshape(50,200)
b = cv.fromarray(a)
cv.SaveImage('saved.png', b)
print b
#Output:
<cvmat(type=42424006 64FC1 rows=50 cols=200 step=1600 )>
The numpy array becomes a cvmat, and the size is unchanged. This is the saved image:

Resources