iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 9
3
Modern Web

慢慢帶你了解Flask系列 第 9

慢慢帶你了解Flask - Day9 網路相簿(5):album顯示(upload修改)

大家好,我是長風青雲。今天已經到了第九天了~

首先相簿的顯示,我們先思考一下如何設計我們的頁面。
第一點就是我們每個人的相簿都不同,然後就像剛剛命名的資料夾一樣,每個人的相簿還分有相冊,相冊中還分有影片和圖片。
第二點是之後我們還能單獨觀看影片和圖片。
然後參考一下一般網路還有app介面,我決定了。
我每個圖片的寬度要設為150。這樣感覺畫面最優良?((其實我這個人沒有審美觀))
(看不懂我說什麼沒關係,我自己也覺得我講的很奇怪,直接看實作後吧!)
https://ithelp.ithome.com.tw/upload/images/20190907/201201164QQ8i6l4Ee.png
https://ithelp.ithome.com.tw/upload/images/20190907/20120116sGWp6CMDFt.jpg
這是實際的樣子,但是你們發現了沒有,影片的部分……手機居然顯示不出來?!
然後我用了各種方式,居然用不出來,開始疑惑youtube是怎麼辦到影片顯示出縮圖的?
所以我打開了youtube,然後用F12大法。
發現了一件不得了的事。
https://ithelp.ithome.com.tw/upload/images/20190907/201201168wshmLhay6.png
我們的影片縮圖,竟然不是<video>標籤而是<image>?!
所以為了大家不要一直再改來改去了,我們今天的目標就是,獲取影片的截圖。

經過拜google和github,我最終看到了一個寫得非常親民的影片截取code。
https://github.com/zhaoxuhui/VideoPreviewer
因為並非原生,我一定要把人家放上來的。
這個人寫的簡單明瞭,所以我非常感謝人家~

我們要做出來的縮圖,只需要截取影片中的一幀,而且我也懶,所以我就截取0分0秒的圖。
程式碼經過修改後,變成了這幅模樣。

import cv2
import numpy as np

video_path = input("Input path of video:\n")
max_width=150
out_path = 'content.jpg'

cap = cv2.VideoCapture(video_path)
video_width = int(cap.get(3))

ratio = max_width * 1.0 / video_width

ret, frame = cap.read()
image=cv2.resize(frame, None, fx=ratio, fy=ratio)
cap.release()

cv2.imwrite(out_path, image)

首先你需要打開cmd輸入
pip install numpy numpy 通常是處理資料組
pip install opencv-python這是個可以處理圖片的module
這個程式碼中,你首先要告訴他,你的影片在哪?
接著他就會自動生成名為content的圖片了。
cv2.VideoCapture(video_path)是讀取影片檔案
https://ithelp.ithome.com.tw/upload/images/20190907/20120116K9ij46Ntmc.png
獲取影片寬度了,因為我個人喜好,所以我希望圖片和影片在album上顯示的寬度為150,所以我便將max_width設為150,而他計算出應該的比率,到時候會進行縮放。
cap.read()會回傳兩個參數,第一個是是否讀到圖片(True跟False),第二個則是截取一幀圖片。
resize字面意思,將圖片依比率放大縮小。
cap.release()既然我們都得到我們要的image了,那我們就應該釋放資源。
cv2.imwrite(out_path, image)將我們的image存在設定好的路徑

既然我們都學會了,那我們來把他加入我們的app.py吧!
之前我說過upload會修改,就是要將我們要再設立album的圖像顯示。真實的圖像是用來以後可以一一檢視的。所以這就來修改我們的upload!(其實之後還會再修一次,畢竟是心路歷程呢……我修改了好多次阿……但我不會讓你們經歷那麼多次)

第一步不要忘記了
import cv2
import numpy as np
接下來我們到創建資料夾那邊將他修改為

				elif request.values['folder']=='1':
					if not os.path.isdir(os.path.join(basepath,session.get('username'),request.values['foldername'])):
						os.mkdir(os.path.join(basepath,session.get('username'),request.values['foldername']))
						os.mkdir(os.path.join(basepath,session.get('username'),request.values['foldername'],'video'))
						os.mkdir(os.path.join(basepath,session.get('username'),request.values['foldername'],'photo'))
						os.mkdir(os.path.join(basepath,session.get('username'),request.values['foldername']),'album')
						os.mkdir(os.path.join(basepath,session.get('username'),request.values['foldername']),'album','video')
						os.mkdir(os.path.join(basepath,session.get('username'),request.values['foldername']),'album','photo')

你是不是有點疑惑為什麼我要多創建album的photo資料夾?為什麼不創建video的就好了,明明剛剛只做了video的圖像呀?
親愛的~這些是明天的事呢!我明天再說((其實是今天累了想偷懶XD
然後就像upload_path一樣,我們要告訴他我們影像縮圖要存在哪兒~
於是就把原先給video的upload_path的地方加上album_path

if format == '.mp4':
						upload_path = os.path.join(basepath,session.get('username'),request.values['foldername'],'video',str(fileName).replace('.','')+str(format))
						album_path = os.path.join(basepath,session.get('username'),request.values['foldername'],'album','video',str(fileName).replace('.','')+'.jpg')
						
					else:
						upload_path = os.path.join(basepath,session.get('username'),request.values['foldername'],'photo',str(fileName).replace('.','')+str(format))					
				else:
					if format == '.mp4':
						upload_path = os.path.join(basepath,session.get('username'),dirs[int(request.values['folder'])],'video',str(fileName).replace('.','')+str(format))
						album_path = os.path.join(basepath,session.get('username'),dirs[int(request.values['folder'])],'album','video',str(fileName).replace('.','')+'.jpg')
					else:
						upload_path = os.path.join(basepath,session.get('username'),dirs[int(request.values['folder'])],'photo',str(fileName).replace('.','')+str(format))
					

告訴完我們要存好的路徑後,剛剛我們寫的影片縮圖要登場啦!
我們要存的是檔案是video的時候,於是我們就再f.save()後面加上

				if format =='.mp4':
					video_photo(upload_path,album_path)

還有在寫一個新function(他只是個function不是需要連到哪裡的所以不用加上app.route的裝飾器喔)

def video_photo(video_path,out_path):
	max_width=150

	cap = cv2.VideoCapture(video_path)
	video_width = int(cap.get(3))

	ratio = max_width * 1.0 / video_width

	ret, frame = cap.read()
	image=cv2.resize(frame, None, fx=ratio, fy=ratio)
	cap.release()

	cv2.imwrite(out_path, image)

應該經過上面解釋,我並不需要特別解釋這一塊。
我在upload的function裡寫的是video_photo(upload_path,album_path),我在新的function的地方告訴他前面的參數是我們之前的video_path,後方則是我們之前的out_path。
然後就來看看我們實作後的圖片吧~
https://ithelp.ithome.com.tw/upload/images/20190907/20120116n0cY7Nzg7u.png
https://ithelp.ithome.com.tw/upload/images/20190907/20120116cAXlADj8pJ.jpg
Wow!!!已經呈現我們想像中的樣子啦!
可是你們發現沒有,因為我們設定長寬都要是150,所以我們的圖片長相都變形了,這樣是不是很醜呢?所以明天我要說的就是將他變得好看的樣子喔~
今天我並沒有告訴大家album本身的程式碼,這可能會拖到後天,等到我將圖片那些調整後,後天我會好好將album講一遍的^w^。
https://ithelp.ithome.com.tw/upload/images/20190907/20120116XvHZYcnmlB.png


上一篇
慢慢帶你了解Flask - Day8 網路相簿(4):上傳檔案
下一篇
慢慢帶你了解Flask - Day10 網路相簿(6):album顯示-2(upload修改)
系列文
慢慢帶你了解Flask30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
阿瑜
iT邦研究生 4 級 ‧ 2019-09-12 13:28:47
有沒有設定說 ,如果我丟一個`不公開的相片`或影片的 權限方面調整 ?

這個、我打算以後再寫~
我有放在github裡的readme提醒自己哪些功能未完成

我要留言

立即登入留言