J'ai déjà fait ça avec succès, inspiré par ce post StackOverflow qui correspond exactement à ta demande :
La réponse propose une solution en pur Python avec OpenCV. Je l'utilise moi-même et ça fonctionne plutôt bien, même depuis une vidéo prise au smartphone.
Voici mon adaptation : un script unique qui prend une vidéo en entrée, extrait les frames significatives (via détection de keypoints ORB) et les assemble en panorama.
Installation :
pip install opencv-python numpy
vid2pano.py :
#!/usr/bin/env python3# https://stackoverflow.com/a/66378715importcv2importnumpyasnpimportosimportshutilimportargparse# rescale the images (1.00 = original / 0.5 = half size)defrescale(img):scale=1.00h,w=img.shape[:2]h=int(h*scale)w=int(w*scale)returncv2.resize(img,(w,h))# decimate functiondefdecimate(input_file):# delete and create directoryfolder="frames/"ifos.path.isdir(folder):shutil.rmtree(folder)os.mkdir(folder)# open vidcapcap=cv2.VideoCapture(input_file)counter=0# make an orb feature detector and a brute force matcherorb=cv2.ORB_create()bf=cv2.BFMatcher(cv2.NORM_HAMMING,crossCheck=False)# store the first frame_,last=cap.read()last=rescale(last)cv2.imwrite(folder+str(counter).zfill(5)+".png",last)# get the first frame's stuffkp1,des1=orb.detectAndCompute(last,None)# cutoff, the minimum number of keypointscutoff=50# count number of framesprev=NonewhileTrue:# get frameret,frame=cap.read()ifnotret:break# resizeframe=rescale(frame)# count keypointskp2,des2=orb.detectAndCompute(frame,None)# matchmatches=bf.knnMatch(des1,des2,k=2)# lowe's ratiogood=[]form,ninmatches:ifm.distance<0.5*n.distance:good.append(m)# check against cutoffprint(len(good))iflen(good)<cutoff:# swap and savecounter+=1last=framekp1=kp2des1=des2cv2.imwrite(folder+str(counter).zfill(5)+".png",last)print("New Frame: "+str(counter))# showcv2.imshow("Frame",frame)cv2.waitKey(1)prev=frame# also save last framecounter+=1cv2.imwrite(folder+str(counter).zfill(5)+".png",prev)# check number of saved framesprint("Counter: "+str(counter))# stitcher functiondefstitcher():# target folderfolder="frames/"# load imagesfilenames=os.listdir(folder)images=[]forfileinfilenames:# get imageimg=cv2.imread(folder+file)# saveimages.append(img)# use built in stitcherstitcher=cv2.Stitcher_create()(status,stitched)=stitcher.stitch(images)cv2.imwrite("result.png",stitched)# main functiondefmain():parser=argparse.ArgumentParser(description="Process a video file.")parser.add_argument('-input',type=str,required=True,help='Input video file')args=parser.parse_args()decimate(args.input)stitcher()if__name__=="__main__":main()
Utilisation :
python vid2pano.py -input ma-video.mp4
Le résultat est dans result.png. Le paramètre cutoff (par défaut 50) contrôle le nombre de keypoints minimum pour considérer qu'une frame est suffisamment différente de la précédente — à ajuster selon ta vidéo.
# vid2pano.py
Posté par i M@N (site web personnel) . En réponse au message Transformer une vidéo de travelling en photo panoramique ?. Évalué à 10 (+9/-0).
Salut,
J'ai déjà fait ça avec succès, inspiré par ce post StackOverflow qui correspond exactement à ta demande :
La réponse propose une solution en pur Python avec OpenCV. Je l'utilise moi-même et ça fonctionne plutôt bien, même depuis une vidéo prise au smartphone.
Voici mon adaptation : un script unique qui prend une vidéo en entrée, extrait les frames significatives (via détection de keypoints ORB) et les assemble en panorama.
Installation :
vid2pano.py :
Utilisation :
Le résultat est dans
result.png. Le paramètrecutoff(par défaut 50) contrôle le nombre de keypoints minimum pour considérer qu'une frame est suffisamment différente de la précédente — à ajuster selon ta vidéo.wind0w$ suxX, GNU/Linux roxX!