アフィリエイト広告を利用しています

広告

この広告は30日以上更新がないブログに表示されております。
新規記事の投稿を行うことで、非表示にすることが可能です。
posted by fanblog

2021年05月29日

私を模倣をするAI(ゲーム編)その1(見本をみせる)

主な開発環境
・Raspbian GNU/Linux 10 (buster)
・python 3.7.3
・tensorflow 1.13.1(1.14.0ではtensorflow.cotribがみつかりませんとエラーが出ます)
・gym 0.15.7
・baselines

環境整備は、概ねpip3 installで対応できます。色々と足りないと言われたら、その都度pip3 installで対応しました。しかし、baselinesのみpip3 installでエラーが出たので、
$ git clone https://github.com/openai/baselines.git
$ cd baselines
$ pip3 install -e .
でインストールしました。

環境が整備できたので、まずは私自身がゲームをプレイし、それを記録します。
こちらの、大変すばらしいページを参考にしました。
https://ailog.site/2020/05/17/0517/
プレイするゲームは、私の好きなゲームに変更しています。

以下は変更箇所
env = gym.make('Breakout-v0') #プレイするゲームをBreakout-v0に変更
env = MaxAndSkipEnv(env, skip=1)  #行動を1フレームごとに選択に変更
def human_expert(_state):
key_state = get_key_state()
action = 1 # 行動の初期値を1にし、すぐにボールが出てくるように変更
generate_expert_traj(human_expert, 'breakout_demo', env, n_episodes=10) #エピソード数を10に変更


1回あたり5個のボールを使えるゲームを10回遊び、私の見本とします。

download.png

2021年05月10日

好みの顔の判別器をラズパイに実装し、webブラウザで判別結果を表示

2000枚以上の顔写真から、

好みの顔と好みでない顔を手作業で選び、

好みの顔の特徴量を学習したHAAR判別器を作成しました。

詳しくはこちら


せっかく作った判別器なので、

手軽に利用できるように、webブラウザをもちいて、

webサーバーに顔写真を投稿すると、

そこに移っている顔が私の好みの顔に該当すると、

赤い矩形で囲んでくれるcgiプログラムを作成しました。

こんな感じです。
2021-05-10 (6).png

cgiプログラムは以下の感じです。
#!/usr/bin/env python3
# coding: utf-8
import cv2
import datetime
import cgi
import os
import io,sys
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
from PIL import Image


password="適当に決めてください"
today=str(datetime.date.today())
path="/prefer_face/" #アップロードされたファイルを保存するディレクトリ
MEGA = 100000000 # 一度にアップロードするデータサイズ
cgi.maxlen=400000000
cascade_path="/prefer_face/cascade.xml" #私の好みを学習したHAAR分類器へのパス


# 入力フォーム
_input_form = """
<html>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<head>
<title>顔写真投稿フォーム</title>
</head>
<body>
<form action enctype="multipart/form-data" method="post">
顔画像の投稿にはパスワードが必須です:<input type="password" name="pass" value="" size="10">
<br><br><br>
顔画像投稿
<p>今日は %s です</p>
File name:
<input type="file" name="foobar" required>
<input type="submit" value="Upload">
</form>
</body>
</html>
"""

# 出力フォーム
_output_form = """
<html>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<head>
<title>好みの顔の判別</title>
</head>
<body>
<h2>判別結果</h2>
<p>顔画像</p>
<p><img src="%s">
</body>
</html>
"""



form = cgi.FieldStorage() #入力フォームでpostされたデータを扱う

if form.getvalue('pass','')==password:
file_name = form["foobar"].filename #ファイル名を取得
full_path = path + file_name #ファイル名にパスを付加
if os.path.exists(full_path): #上書き確認
sys.exit(0)

data_1=str(file_name) #ファイル名をテキストとして収容
data_2=str(full_path)

uploaded_file = open(full_path, 'wb') #アップロードされたデータを保存する新規ファイルを同名で作成
item = form['foobar']
while True:
chunk = item.file.read(MEGA)
if not chunk:
break
uploaded_file.write(chunk)
uploaded_file.close()


image = cv2.imread(data_2) #ファイル読み込み
cascade = cv2.CascadeClassifier(cascade_path) #顔の特徴から判別
#私の好みの顔であれば赤い矩形で囲まれるスクリプト
facerect = cascade.detectMultiScale(image, scaleFactor=1.1, minNeighbors=1, minSize=(50, 50))
if len(facerect) >0:
#好みの顔を囲む矩形の作成
for rect in facerect:
cv2.rectangle(image, tuple(rect[0:2]), tuple(rect[0:2]+rect[2:4]), (0,0,255), thickness=2)
#認識結果の保存
cv2.imwrite("/prefer_face/preferface_detected.jpg", image)

print (_output_form % ("/prefer_face/preferface_detected.jpg"))

else:
print (_input_form % (today))


2021年05月09日

ラズパイ4にjupyter notebookを導入し、サーバー化して接続

開発環境
・Raspbian GNU/Linux 10 (buster)
・python 3.7.3
・matplotlib 3.02
・opencv 4.1.0
・pygame 1.9.6
追加機能
・Jupyter Notebook

基本的に、ラズパイにはモニタを接続せずに、

お部屋の片隅で、監視カメラと温度・湿度のモニターを

行わせています。

ラズパイに、新たなことを行わせるときは、

sshで遠隔接続して、命令を入力しています。


前回、AIの学習環境を整えたので、

今回は、実際に学習させる命令やプラグラムを書く便利な作業環境を整えたいと思います。

以下を参考にしました。
Raspberry Pi で Jupyter Notebook
https://smile-jsp.hateblo.jp/entry/2019/09/25/102751

SSH先のサーバ上のjupyter notebookをローカルPCで操作する
https://sishida21.github.io/2019/12/12/remote-jupyter-notebook/

まずはお決まりのアップデートとアップグレード。
$ sudo apt-get update
$ sudo apt-get upgrade

pythonを最新versionに。
$ sudo apt-get install python3 python-dev build-essential python-pip

pipを最新versionに。
$ sudo python3 -m pip install --upgrade pip

Jupyter Notebookをインストール。
$ sudo pip3 install jupyter

Jupyter Notebookのデフォルト設定ファイルを作成。
$ jupyter-notebook --generate-config
デフォルト設定ファイルが作成された場所が表示されます。
ユーザー名がpi(初期値)であれば/home/pi/.jupyter/jupyter_notebook_config.pyと表示されるはずです。

そのデフォルト設定を2か所編集して、遠隔で接続できるようにします。
私の場合、編集にはnanoを用いました。
$ sudo nano /home/pi/.jupyter/jupyter_notebook_config.py
ずらずらと文字ができくるので、該当の場所を探します。
1つ目(ブラウザの自動起動の抑止)
編集前 # c.NotebookApp.open_browser = True
編集後 c.NotebookApp.open_browser = False
2つ目(listen アドレスの変更)
編集前 # c.NotebookApp.ip = localhost
編集後 c.NotebookApp.ip = 0.0.0.0
以上のように編集した後、保存します。

次にパスワードを設定します。
$ jupyter notebook password
自分で決めたパスワードを入れます。

以上で終了です。

では、実際にWindowsのTeraTermからラズパイのjupyter notebookを起動し、
Windowsのブラウザから開いて、簡単な図を表示させてみます。
2021-05-09 (2).png
成功です。

2021年03月21日

ラズパイ4にAI関連をセットアップ

開発環境
・Raspbian GNU/Linux 10 (buster)
・python 3.7.3

こちらのページを参考に

我が家のRaspberry Pi4(通称2号機)に

AI関連のアプリやデータをセットアップしていきます。

今回は、

opencvといった代表的な画像解析をするためのセットアップをしました。

システムアップデート
$ sudo apt update
$ sudo apt upgrade -y
$ sudo reboot

-yは途中yesかnoを問われたときに全てyesで解答するという指示です。無しの場合は、その都度yesかnoの解答をすれば良いです。

データ処理パッケージのインストール
$ sudo apt install python3-numpy
$ sudo apt install python3-pil
$ sudo apt install python3-pandas
$ sudo apt install python3-matplotlib
$ sudo apt install python3-sklearn

Tensorflowのインストール
$ sudo pip3 install -U pip
$ sudo pip3 install -U setuptools
$ sudo pip3 install wrapt --upgrade --ignore-installed
$ sudo pip3 install --default-timeout=1000 tensorflow==1.13.1

最新版はver2となっていますが、ラズパイに対応しているらしい
ver1.13.1をセットアップしました。

OpenCVのインストール
$ sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev libpng-dev
$ sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
$ sudo apt-get install libxvidcore-dev libx264-dev
$ sudo apt-get install libatlas-base-dev gfortran
$ sudo apt-get install libhdf5-dev libhdf5-serial-dev libhdf5-103
$ sudo apt-get install libqtgui4 libqtwebkit4 libqt4-test python3-pyqt5
$ pip3 install opencv-contrib-python==4.1.0.25
$ pip3 install opencv-python==4.1.0.25
以上

2021年03月07日

ラズパイにAIを実装する

学習により作成した私のAIを、

どのようにして現実世界に実装するかを

考えたとき、

ラズパイを思いつきました。

カメラモジュールやGPIOを備えているため、

各種センサーを取り付ければ、

センサーの測定結果をもとに、

AIに判断させ、

行動するようにセットすることも簡単に可能です。

ただ、処理能力は高いとは言えません。

しかし、私のAIならば、

そのくらいの処理能力で十分かとも思っています。




2020年09月12日

python、cgi、sqlite3にてUnicodeEncodeErrorに苦戦、一応、解決

WordPressはきれいだし、
導入も簡単で、
初心者でも本格的なHPやブログを作成できることは、
私も試したから知っています。

でも、なんか、型にはまった感じがつまらなく、

結局、html、css、cgiをできるだけ自分で書き、

ページが表示されたときの感動がうれしいので、

わざわざ苦労して、書いています。


今回、

1 sqlite3のデータベースに入力

2 画像のURLやコメントをpythonで読み込み

3 webに表示する。

の3で苦戦したので、備忘録です。

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/python
# -*- coding: utf-8 -*-
import cgi
import sqlite3

print ("""
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8"> </head>
<title>私の読書感想文</title>
</head>
<body>""")
conn=sqlite3.connect("/book.db")
c=conn.cursor()
for row in c.execute("select * from book_list"):
a=row[2]
b=a.encode("utf-8")
print("""<p>%s</p>""")%(b)
conn.close()

print("""
</body>
</html>
""")



データベースの3列目(row[2])に入力した全角の日本語(utf-8)が表示できず、二日間苦戦しました。

apache2のerror.logを読むと下記のエラー
UnicodeEncodeError: 'ascii' codec can't encode character

おかしいな〜?

python上で #-*-coding: utf-8-*-

html上で charset=utf-8

を宣言しているのに、なぜエンコードエラーがでるのだ?

ネット内の情報を調べまくりました。

結果的に、必要だったのは上記.cgiの18行目です。

sqlite3nデータベースからpythonで読み込んだ日本語は、

なぜかUnicodeで読み込んでいるので、utf-8とUnicodeでケンカしていたようです。

そこで、18行目に

b=a.encode("utf-8")

を挿入し、sqlite3から読み込んだ全角の日本語を改めてutf-8にエンコードしました。

これによって、日本語がcgiで表示できました。

たどり着くまでに2日かかりました。

Screenshot from 2020-09-12 19-47-32.png

2020年08月29日

米津玄師さんのラジオは土曜日

今日、

17時から買い物に行く際の車中で、

FMラジオを聞いていたら、

米津さんのラジオが流れていました。

10代を中心に悩みを読み上げ、それに答える米津さんは

真摯で、40代の私の心にも響きました。

・3歳からバレーをやっている少女が2年前からやる気を失い、日々つらい
・医療で働くが、自分の命と他者を助けることの天秤にはまってしまったこと
・締切を守れない10代が、今のうちにこの性格を直したい
・自己を主張したい。でも主張すべきではない?

等、

私も、分野としてはほぼ同じことを20年続け、正直、飽きてきました。

上記のうち、特に米津さんのコメントで同調したのが、
「自己を主張したいならば、逆説的に、自己をいかに主張しない作品をつくるかをつきるめることで、
結論に達すると思う。」
です。あれだけ、ご自身の楽曲がある中で、
「他者へ提供することもあり、自身の存在を消したいと作品をつくったが、それでも消せない、エゴがあり、それが自己である。」 
みたいなコメントが非常に心に響きました。

私はサラリーマンであり、自己を主張することはありませんが、それでも自己は出てきてしまいます。もっと消せれば、生産性が上がるのではと思っているくらいでした。

米津さんみたいなアーティストが、自己を消そうと努力していることもあることに驚きました。

でも、逆説です。自己を消すだけしても残ったものが自己との、強い主張を感じました。

私も、結果的に残ってしまった自己を、否定せず、それを逆に大事にしていきたいと思いました。


2020年07月04日

遺伝的アルゴリズムという響きに引き寄せられる

機械的なプログラミングにあって

生物学のシステムを取り入れたのが

遺伝的アルゴリズム?

これについて、

使いこなせるまで

しばらく

備忘録として

このブログを使う予定です。

2020年05月24日

pygame 途中ですがブロックゲーム

壁PingPongの次は、
ブロックゲームでしょ。

どうしてもcontainersが馴染めず、
group.addにこだわりました。

とりあえず、ここまで出来ました。
画像をダウンロードして、プログラムをコピーすれば動きます。

racket.png
bar_B.png
gold.png
platinium.png
ruby.png
silver.png
ball.png
output2.gif

#!usr/bin/env python
#coding:utf-8
import pygame
from pygame.locals import*
import sys
import random

START,PLAY,GAMEOVER,GAMECLEAR=(0,1,2,3)
SCR_RECT=Rect(0,0,480,640)
RACKET_MOVE_RECT=Rect(0,320,480,320)

class WallPingPong():
def __init__(self):
self.counter=0
self.score=0
pygame.init()
self.screen=pygame.display.set_mode(SCR_RECT.size)
pygame.display.set_caption(u"壁ピンポン!!")
self.load_images()
self.init_game()
clock=pygame.time.Clock()
while True:
clock.tick(60)
self.update()
self.draw(self.screen)
pygame.display.update()
self.key_handler()
else:
self.game_state=PLAY

def init_game(self):
self.game_state=START
self.racket=Racket()
self.enemy=Enemy()
self.ball_list=[Ball(10,10,self.racket,self.enemy),
Ball(3,4,self.racket,self.enemy),
Ball(-2,5,self.racket,self.enemy),
Ball(-6,8,self.racket,self.enemy)]
self.map_data=[[0,0,0,0,0,0,0,0,0],
[1,1,0,2,3,2,1,1,1],
[0,1,1,4,1,1,0,1,1],
[1,3,0,2,2,2,1,1,1],
[0,1,1,4,1,1,4,1,1],
[0,3,1,4,1,1,0,1,1],
[1,1,0,2,2,2,1,1,1],
[0,0,0,0,3,0,0,0,0]]
self.block_list=[]
for x in range(9):
for y in range(8):
if self.map_data[y][x]==1:
self.block_list.append(Block_Gold(x,y,self.ball_list))
elif self.map_data[y][x]==2:
self.block_list.append(Block_Platinium(x,y,self.ball_list))
elif self.map_data[y][x]==3:
self.block_list.append(Block_Ruby(x,y,self.ball_list))
elif self.map_data[y][x]==4:
self.block_list.append(Block_Silver(x,y,self.ball_list))
self.group1=pygame.sprite.RenderUpdates()
self.group2=pygame.sprite.RenderUpdates()
self.group3=pygame.sprite.RenderUpdates()
self.group1.add(self.racket,self.enemy)
self.group2.add(self.ball_list)
self.group3.add(self.block_list[0:random.randint(1,47)])
self.balls=pygame.sprite.Group(self.group2)
self.blocks=pygame.sprite.Group(self.group3)

def update(self):
if self.game_state==PLAY:
self.counter+=1
self.group1.update()
self.group2.update()
self.group3.update()
if len(self.balls.sprites())==0:
self.game_state=GAMEOVER
if pygame.sprite.groupcollide(self.group2,self.group3,False,False):
self.score+=10
if len(self.blocks.sprites())==0:
self.game_state=GAMECLEAR

def draw(self,screen):
screen.fill((0,0,0))
if self.game_state==START:
title_font=pygame.font.SysFont(None,80)
title=title_font.render("Wall PingPong!!",True,(255,0,0))
screen.blit(title,((SCR_RECT.width-title.get_width())//2,100))
push_font=pygame.font.SysFont(None,40)
push=push_font.render("PUSH SPACE KEY",True,(255,255,255))
screen.blit(push,((SCR_RECT.width-push.get_width())//2,SCR_RECT.centery))
self.group1.draw(screen)
elif self.game_state==PLAY:
self.group1.draw(screen)
self.group2.draw(screen)
self.group3.draw(screen)
stat_font=pygame.font.SysFont(None,36)
stat=stat_font.render("Score:{:05d} Counter:{:05d}".\
format(self.score,self.counter),True,(255,0,0))
screen.blit(stat,(0,0))
elif self.game_state==GAMEOVER:
stat_font=pygame.font.SysFont(None,36)
stat=stat_font.render("Score:{:05d} Counter:{:05d}".\
format(self.score,self.counter),False,(255,0,0))
screen.blit(stat,(0,0))
gameover_font=pygame.font.SysFont(None,80)
gameover=gameover_font.render("GAMEOVER",True,(255,255,255))
screen.blit(gameover,((SCR_RECT.width-gameover.get_width())//2,100))
push_font=pygame.font.SysFont(None,40)
push=push_font.render("PUSH SPACE KEY",True,(255,255,255))
screen.blit(push,((SCR_RECT.width-push.get_width())//2,SCR_RECT.centery))
cresit_font=pygame.font.SysFont(None,20)
cresit=cresit_font.render("2020 by https://fanblogs.jp/aimyself/",True,(255,255,255))
screen.blit(cresit,((SCR_RECT.width-cresit.get_width())//2,600))
elif self.game_state==GAMECLEAR:
stat_font=pygame.font.SysFont(None,36)
stat=stat_font.render("Score:{:05d} Counter:{:05d}".\
format(self.score,self.counter),False,(255,0,0))
screen.blit(stat,(0,0))
gameover_font=pygame.font.SysFont(None,80)
gameover=gameover_font.render("GAMECLEAR",True,(255,255,255))
screen.blit(gameover,((SCR_RECT.width-gameover.get_width())//2,100))
push_font=pygame.font.SysFont(None,40)
push=push_font.render("PUSH SPACE KEY",True,(255,255,255))
screen.blit(push,((SCR_RECT.width-push.get_width())//2,SCR_RECT.centery))
cresit_font=pygame.font.SysFont(None,20)
cresit=cresit_font.render("2020 by https://fanblogs.jp/aimyself/",True,(255,255,255))
screen.blit(cresit,((SCR_RECT.width-cresit.get_width())//2,600))

def key_handler(self):
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
elif event.type==KEYDOWN and event.key==K_ESCAPE:
pygame.quit()
sys.exit()
elif event.type==KEYDOWN and event.key==K_SPACE:
if self.game_state==START:
self.game_state=PLAY
elif self.game_state==GAMEOVER:
self.score=0
self.counter=0
self.init_game()
self.game_state=PLAY
elif self.game_state==GAMECLEAR:
self.score=self.score
self.counter=0
self.init_game()
self.game_state=PLAY

def load_images(self):
Racket.image=load_image("racket.png")
Enemy.image=load_image("bar_B.png")
Ball.image=load_image("ball.png")
Block_Gold.image=load_image("gold.png")
Block_Platinium.image=load_image("platinium.png")
Block_Ruby.image=load_image("ruby.png")
Block_Silver.image=load_image("silver.png")

class Racket(pygame.sprite.Sprite):
speed=10
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.rect=self.image.get_rect()
self.rect.center=(SCR_RECT.width/2,SCR_RECT.height/5*4)
def update(self):
pressed_keys=pygame.key.get_pressed()
if pressed_keys[K_LEFT]:
self.rect.move_ip(-self.speed,0)
if pressed_keys[K_RIGHT]:
self.rect.move_ip(self.speed,0)
if pressed_keys[K_UP]:
self.rect.move_ip(0,-self.speed)
if pressed_keys[K_DOWN]:
self.rect.move_ip(0,self.speed)
self.rect.clamp_ip(RACKET_MOVE_RECT)

class Enemy(pygame.sprite.Sprite):
speed=10
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.rect=self.image.get_rect()
self.rect.center=(SCR_RECT.width/3,SCR_RECT.height/5*4)
def update(self):
self.rect.center=pygame.mouse.get_pos()
self.rect.clamp_ip(RACKET_MOVE_RECT)

class Ball(pygame.sprite.Sprite):
def __init__(self,vx,vy,racket,enemy):
pygame.sprite.Sprite.__init__(self)
self.rect=self.image.get_rect()
self.rect.center=(SCR_RECT.width/2,SCR_RECT.height/5*4)
self.vy=vy
self.vx=vx
self.racket=racket
self.enemy=enemy
def update(self):
self.rect.move_ip(self.vx,self.vy)
if self.rect.left<0 or self.rect.right>SCR_RECT.width:
self.vx=-self.vx
if self.rect.top<SCR_RECT.top:
self.vy=-self.vy
if self.rect.colliderect(self.racket.rect) and self.vy>0:
self.vy=-self.vy
if self.rect.colliderect(self.enemy.rect) and self.vy>0:
self.vy=-self.vy
if self.rect.bottom>SCR_RECT.bottom:
self.kill()

class Block_Gold(pygame.sprite.Sprite):
def __init__(self,x,y,ball_list):
pygame.sprite.Sprite.__init__(self)
self.rect=self.image.get_rect()
self.rect.left=SCR_RECT.left+x*self.rect.width+5*(x+1)
self.rect.top=SCR_RECT.top+y*self.rect.height+5*(y+1)
self.ball_list=ball_list
self.hardness=3
def update(self):
for i in range(0,4):
if self.rect.colliderect(self.ball_list[i].rect)>0:
self.ball_list[i].vy=-self.ball_list[i].vy
self.hardness+=-1
if self.hardness<=0:
self.kill()

class Block_Platinium(pygame.sprite.Sprite):
def __init__(self,x,y,ball_list):
pygame.sprite.Sprite.__init__(self)
self.rect=self.image.get_rect()
self.rect.left=SCR_RECT.left+x*self.rect.width+5*(x+1)
self.rect.top=SCR_RECT.top+y*self.rect.height+5*(y+1)
self.ball_list=ball_list
self.hardness=4
def update(self):
for i in range(0,4):
if self.rect.colliderect(self.ball_list[i].rect)>0:
self.ball_list[i].vy=-self.ball_list[i].vy
self.hardness+=-1
if self.hardness<=0:
self.kill()
class Block_Ruby(pygame.sprite.Sprite):
def __init__(self,x,y,ball_list):
pygame.sprite.Sprite.__init__(self)
self.rect=self.image.get_rect()
self.rect.left=SCR_RECT.left+x*self.rect.width+5*(x+1)
self.rect.top=SCR_RECT.top+y*self.rect.height+5*(y+1)
self.ball_list=ball_list
self.hardness=9
def update(self):
for i in range(0,4):
if self.rect.colliderect(self.ball_list[i].rect)>0:
self.ball_list[i].vy=-self.ball_list[i].vy
self.hardness+=-1
if self.hardness<=0:
self.kill()

class Block_Silver(pygame.sprite.Sprite):
def __init__(self,x,y,ball_list):
pygame.sprite.Sprite.__init__(self)
self.rect=self.image.get_rect()
self.rect.left=SCR_RECT.left+x*self.rect.width+5*(x+1)
self.rect.top=SCR_RECT.top+y*self.rect.height+5*(y+1)
self.ball_list=ball_list
self.hardness=2
def update(self):
for i in range(0,4):
if self.rect.colliderect(self.ball_list[i].rect)>0:
self.ball_list[i].vy=-self.ball_list[i].vy
self.hardness+=-1
if self.hardness<=0:
self.kill()

def load_image(filename):
image=pygame.image.load(filename).convert_alpha()
return image

if __name__=="__main__":
WallPingPong()
posted by もう一人の自分 at 17:51| pygame

2020年05月06日

ファンブログへのGIF投稿には縦320で!〜描画への対策〜

自作GIFのアイコンがWEB上できれいに表示されないのは?

ファンブログでGIFを掲載した際、

動画が綺麗に描画されず、色々と調べました。

結果、ファンブログの画像管理は、

Screenshot from 2020-05-06 22-54-08.png
サムネイル長辺のpx数 320px

で初期設定されている。

そこで、

ffmpegで縦320pxにしてgif出力する。

$ ffmpeg -i 元ファイル名.mp4 -vf scale=-1:320 出力ファイル名.gif

それを、アップロードすると

サムネイルにて綺麗に表示されました。
検索

私が見た動画紹介コーナー

素敵です

プロフィール
もう一人の自分さんの画像
もう一人の自分
好きなことを仕事にしなかった
プロフィール
最新記事
カテゴリーアーカイブ
ファン
写真ギャラリー
×

この広告は30日以上新しい記事の更新がないブログに表示されております。