Briswell Tech Blog

ブリスウェルのテックブログです

文章から画像を生成してみよう

こんにちは.AI,IoT担当の大澤です.

最近AI界隈では文章から画像を生成するText to Imageタスクの分野で大変な盛り上がりを見せていました. OpenAIのDALL-E2GoogleImagenなど,高画質で高精度な画像を生成するモデルが相次いで発表されたことが大きいのではないでしょうか.

Text to Imageとは読んで字のごとく,入力された文字列をもとに画像を生成するタスクのことです.下の画像を見てみましょう.

麦わら帽子とサングラスを身に着けたサボテンですね.Photoshopで作られた作品のように見えますが…実はこちら,Googleが発表したImagenというAIが作成したものです.

こちらはまずAIへの入力として「A small cactus wearing a straw hat and neon sunglasses in the Sahara desert.」という文章が与えられます.日本語訳では「サハラ砂漠で麦わら帽子をかぶり、ネオンサングラスをかけた小さなサボテン。」です.

するとこの画像が出力されるわけです.しっかりと文章の意味を理解し,的確に画像へと変換されています.

「A photo of a Corgi dog riding a bike in Times Square. It is wearing sunglasses and a beach hat.(タイムズスクエアで自転車に乗っているコーギー犬の写真。サングラスとビーチハットをかぶっています。)」という文章を与えると次のような画像が生成されるようです.

面白いですね.実は今までにもこのようなタスクができるモデルはあったのですが,transformerや拡散モデルなど,近年生まれた技術の組み合わせでここまでクオリティの高い画像生成を行うことができるようになったようです.

ただ,これらは膨大な計算リソースを必要とするため,一般的なPCなどでは実行できません.代わりに計算量を大幅に削減したモデルで,画像生成を体験してみましょう.

こちらのサイトに掲載されているgooglecolabのdemoコードを使用させていただきました.

www.12-technology.com

まずはimagenのサイトにもあった文章と同じものを入れてみましょう.

A photo of a Corgi dog riding a bike in Times Square. It is wearing sunglasses and a beach hat.

流石にGoogleのようにはいきませんが,それっぽく見える画像が生成できました.

他にも色々試してみましょう.

A photo of snowman sunbathing on a beach in summer. Snowman is wearing sunglasses and a beach hat.

真ん中上部のガッツポーズが最高ですね.

Photo of a cat wearing sunglasses at the wheel of a convertible.

左下のボケ感がじわじわきますね.

Illustration of a sunflower wearing sunglasses eating ice cream.

イラスト風にもできました.

とてもおもしろいですね.夏なのでサングラス多めでお送りしました. それでは.

Pythonで夏を感じる

厳しい暑さが続きますね!
この1週間、ずっと30℃超えが当たり前で梅雨はどこ?って思っておりましたが、やはり梅雨明けしたようです。

OpenWeatherMapAPIにより全世界の天気データを取得できます。
PythonからこのAPIを呼び出し、取得した天気データをグラフ化して、一足先に夏を感じたいと思います。

1. モジュールのインポート

import requests
import pandas as pd
import plotly.graph_objects as go
from pytz import timezone
from datetime import datetime

APIKEY = "" #APIキー
LATITUDE = "" #緯度
LONGITUDE = "" #経度
BG_COLOR = "#100500" #グラフ背景色
FONT_COLOR = "#fff5f3" #グラフ文字色
TITLE = "東京都港区の体感気温と湿度" #グラフタイトル

2. 天気情報を取得

url = "http://api.openweathermap.org/data/2.5/onecall"
payload = {"lat": LATITUDE, "lon": LONGITUDE, "lang": "ja", "units": "metric", "APPID": APIKEY}
weather_data = requests.get(url, params=payload).json()
tz = timezone(weather_data['timezone'])
wd = weather_data['hourly'] # 現在から48時間先までの1時間毎のデータを取得

3. 日時、体感気温、湿度をリスト化

weather_data_list = []
for w1 in wd:
    tmp_dict = {}
    tmp_dict['日時'] = datetime.fromtimestamp(w1['dt'], tz=tz).strftime("%m/%d %H時")
    tmp_dict['体感気温℃'] = int(w1['feels_like'])
    tmp_dict['湿度%'] = int(w1['humidity'])
    weather_data_list.append(tmp_dict)

df_temp = pd.json_normalize(weather_data_list)

4. グラフ化

# X軸:日時、Y軸:体感気温
trace1 = go.Scatter(
    x = df_temp['日時'],
    y = df_temp['体感気温℃'],
    mode = 'lines',
    name = '体感気温℃',
    yaxis='y1',
    line=dict(color='#da70d6')
)

# X軸:日時、Y軸:湿度
trace2 = go.Scatter(
    x = df_temp['日時'],
    y = df_temp['湿度%'],
    mode = 'lines',
    name = '湿度%',
    yaxis='y2',
    line=dict(color='#87cefa')
)

# Y2軸グラフ化
layout = go.Layout(dict(margin=dict(l=0, r=0, t=30, b=0), paper_bgcolor=BG_COLOR, plot_bgcolor=BG_COLOR,
            title=dict(text=TITLE, x=0.5, y=1.0, font=dict(color=FONT_COLOR, size=24), xanchor='center', yanchor='top', pad=dict(l=0, r=0, t=5, b=0)),
            font=dict(color=FONT_COLOR, size=18),
            xaxis=dict(title='日時', showgrid=False),
            yaxis=dict(title='体感気温℃', side = 'left', showgrid=False, range = [10, 40]),
            yaxis2=dict(title='湿度%', side = 'right', overlaying = 'y', showgrid=False, range = [40, 100])
))
fig = go.Figure(dict(data = [trace1,trace2], layout = layout))

# グラフ画像を保存
fig.write_image("weather_graph.png", height=400, width=1600, scale=1)

5. 結果

夏ですね!
ただ日中の湿度はそこまで高くないのでハワイのようにカラッとして過ごしやすそうです。

Pythonで銀河観測

先日、私たちが住んでいる「地球」が属している「太陽系」が属している「天の川銀河」(地球 ⊂ 太陽系 ⊂ 天の川銀河)の中心にあるブラックホールの姿が初めて撮影されました。すごい時代になったものです。

「Uppsala General Catalogue of Galaxies (UGC)」という北半球から見える約1万3千個の銀河のカタログがあります。そのカタログの中に、積分記号( ∫ )のような形の渦巻銀河「UGC 3697」があります。今回はその銀河をPythonで確認してみましょう。

銀河の画像を複数枚タイル状に表示する方法 - Qiita
pythonを用いて銀経銀緯で複数のfits画像を並べてプロットする方法 - Qiita

こちらの記事を参考にさせていただきました。ありがとうございました。

1. モジュールのインポート

from astroquery.vizier import Vizier #Vizierカタログのデータ取得用
from astroquery.skyview import SkyView #fitsファイル取得用
from astropy.wcs import WCS #天球上の座標取得用
from astropy.io import fits #fitsファイル読込用
import glob #ディレクトリのファイル取得用
import matplotlib.pyplot as plt #グラフ描画用

2. カタログ存在確認

catalog = "UGC"
code = "3697"
v = Vizier(catalog="VII/26D/catalog",column_filters={catalog:"="+code})
data = v.query_constraints()
print(data[0])

出力結果は以下です。UGCカタログ(VII/26D/catalog)に存在していますね。

UGC   A   RA1950  DE1950      MCG      MajAxis MinAxis  Hubble Pmag  i 
         "h:m:s" "d:m:s"                arcmin  arcmin         mag     
---- --- ------- ------- ------------- ------- ------- ------- ---- ---
3697     07 05.6  +71 55 MCG+12-07-028    3.30    0.20 INTEGRL 13.1  --

3. fitsファイルを保存

def save(p,name,obs): 
    for onep,oneo in zip(p,obs):
        onep.writeto(name+"_"+oneo+".fits",overwrite=True)

path_fits = "./"
galaxy = catalog+code
olist = ["DSS"] #Digitized Sky Survey

paths = SkyView.get_images(position=galaxy,survey=olist)
save(paths,path_fits+galaxy,olist)

4. fitsファイルを元に画像を作成

# fitsファイルを取得
dss = glob.glob("./*_DSS.fits")

# グラフ描画領域を作成
F = plt.figure(figsize=(6,8))

# fitsファイルの読込
dssfilename = dss[0]
dssname = dssfilename.replace(".fits",".png")
dsshdu = fits.open(dssfilename)[0]
dsswcs = WCS(dsshdu.header)
dssdata = dsshdu.data

# グラフタイトルを定義
plt.figtext(0.45, 0.93, galaxy, size="large")

# オリジナル画像表示
plt.subplot(211, projection=dsswcs) #2行1列の1番目
plt.imshow(dssdata, origin='lower')
plt.grid(color='white', ls='dotted')

# 拡大画像表示
dssxlen, dssylen = dssdata.shape
dsscx = int(0.5 * dssxlen)
dsscy = int(0.5 * dssylen)
dssdx = int(dssxlen * 0.15)
dsswcscut = dsswcs[dsscx-dssdx:dsscx+dssdx,dsscy-dssdx:dsscy+dssdx]

plt.subplot(212, projection=dsswcscut) #2行1列の2番目
plt.imshow(dssdata[dsscx-dssdx:dsscx+dssdx,dsscy-dssdx:dsscy+dssdx], origin='lower')
plt.grid(color='white', ls='dotted')

# 画像保存
plt.savefig(galaxy + ".png")
plt.close()

5. 結果

宇宙に浮かぶ ∫ なんとも素敵ですね...

Pythonで降らせる流星群

4月23日は「4月こと座流星群」の極大でした。

明け方から活動ピークを迎えるということで、夜空を見上げましたが...
やはり都会の明るい夜では、星はかけらも見当たりません。ライブカメラの観測に切り替えました。

今年も数は少なかったですが、明るい流れ星もあり、楽しむことができました。あのキラッと流れるのも見た瞬間は心が躍ります。

さて、今回はその感動を分かち合いたく、満天の星空に流星群を降らせてみます。

GitHub - yu4u/shooting-star-generator: Generate synthetic shooting star images

こちらのコードを参考にさせていただきました。ありがとうございました。

1. 流れ星の形状決め

numpy.random.randint(min,max) # min〜maxの範囲の整数
numpy.random.rand() # 0.0以上、1.0未満

# 80〜180の範囲の整数値を取得する場合
length = 80 + np.random.randint(0,100)

# ランダムな角度を取得する場合
theta = 0.7 * pi * np.random.rand() + 0.2 * pi

NumPyのrandomモジュールを使用して、流れ星の表示時間、長さ、明るさ、ヘッドと尾の部分の大きさ、流す角度等を決める乱数値(ランダムな値)を取得します。

2. 流れ星の画像生成

cv2.line(image, start_point, end_point, color, thickness) # 対象画像、開始座標、終了座標、線の色、線の太さ

OpenCVのline関数を使用して、流れ星のヘッドと尾の線を引きます。

画像を繋げたもの(アニメーションGIF)がこちらになります。

Pythonの画像処理ライブラリPillowのsave関数を使うと、アニメーションGIFを作成することができます。

# 画像imに、画像リスト[im1, im2, ...]を追加してアニメーションGIFを作成する場合
im.save('anime.gif', save_all=True, append_images=[im1, im2, ...])

3. 流れ星を回転・移動

cv2.warpAffine(image, affine, (size_x, size_y)) # 対象画像、アフィン変換の行列、出力のサイズ

放射状に見える流星群のイメージに近づけるために、OpenCVのwarpAffine関数を使用して、流す角度や位置を変えます。

4. 背景を透過

# 黒色(R0 G0 B0)のαチャンネル(画素の不透明度)を0にする場合
image[:, :, 3] = np.where(np.all(image == 0, axis=-1), 0, 255)

満天の星空に降らすために、黒色の背景を透過します。

5. 満天の星空と合成

明日の朝、砂浜にほしのかけら落ちているかしら。

RDS for MySQL 5.6 → 5.7 でのアップデートエラー

RDS Aurora For Mysql 5.6 のサポートが来年2月に切れるとメールが入ったので、いくつかの案件で対応を始めました。
基本的にはコンソールから、バージョンを変更して適用すれば良いのかな、と思っていたのですが、1プロジェクトで、下記画像のエラーが出てしまい、躓きました。

f:id:Toshi_bw:20220331184431p:plain
Error


申し訳ありませんが、DBクラスター xxx を変更するリクエストが失敗しました。
Cannot modify engine version because Instance xxxxx has Performance Insights enabled and the new version doesn't support this feature.

はぁ...
Performance Insights が有効になっているので、更新できないよ。
と言われているのはわかってるのですが、RDSコンソール画面で Performance Insights の有効 / 無効の項目が出てない...


わからないので、AWS サポートに問い合わせを行ったところ、下記回答をいただきました。

調査した結果、お客様の場合は Performance Insights をサポートしていないインスタンスクラス(db.t3.small)をご利用いただいているため、マネジメントコンソール上に Performance Insights メニューが表示されないことが判明しました。恐らく DB インスタンスの変更メニューより何かを変更される際にも、以下のようなメッセージが表示されるかと存じます。 Performance Insights not supported for this configuration, please disable this feature. Performance Insights をサポートするインスタンスクラスで Performance Insights を有効にした状態で、インスタンスクラスを Performance Insights 非サポートのものに変更する場合に、同様な問題が発生することが報告されております。


迅速なご回答に感謝しつつ、 AWS CLI で対応してね、とのことだったので下記ドキュメントを参考しました。

docs.aws.amazon.com

AWS CLI 自体の設定はこちら

docs.aws.amazon.com

結果、実行したコマンドは
aws rds modify-db-instance --db-instance-identifier instance-name --no-enable-performance-insights --profile projectName


こちらで無事無効化を行えました。
その後、RDS コンソールから5.7 へのバージョンアップも無事行えました!!

対応期限にはまだ時間はあるものの、どういったところで躓くかわからないので、色々なプロジェクトに対し早め対応を行っていこうと思います!!

より良いシステム開発・運用を求めて...

Pythonで観る宇宙

桜が見頃になってきましたね!
ついこの間咲き始めたと思ったら、いつの間にやらもう満開。季節の巡りは早いものです。

今回は天体観測をします。
春の夜には早々と消えていきますが...
私の大好きなオリオン座の星雲を観てみます。

赤外線天文衛星「あかり」などの望遠鏡によって撮影された写真をいじってみたり - Qiita

こちらの記事を参考にさせていただきました。ありがとうございました。

Astroqueryというモジュールを使うことで、SkyViewの天文写真をPythonで取得することができます。望遠鏡を覗き込まずに、プログラムから天体観測ができるなんてとても素敵です。

では、いってみましょう。

1. モジュールのインポート

import numpy as np #数値計算用
import matplotlib.pyplot as plt #描画用
from astroquery.skyview import SkyView #天文写真取得用
from astropy import units as u #取得範囲設定用
from astropy.wcs import WCS #天球座標変換用
from astropy.visualization import ZScaleInterval,ImageNormalize #画像補正用

astropyは天文データ解析用のパッケージです。

2. 設定値

target = 'M42' #オリオン大星雲
survey = ['2MASS-K','2MASS-H','2MASS-J'] #近赤外線波長域での天文観測プロジェクト
radius = 30*u.arcmin #取得する写真の範囲
pixels = 600 #取得する写真の大きさ
figsize = [6,6] #画像表示エリアのサイズ

オリオン座の散光星雲を取得する場合は、targetに「NGC 2024」を設定します。

3. 天文写真取得

hdu = SkyView.get_images(target,survey=survey,radius=radius,pixels=pixels) #天文写真を取得
wcs = WCS(hdu[0][0].header) #WCS座標を取得
plt.figure(figsize=figsize).gca(projection=wcs,title=target) #取得した座標をプロットする
plt.imshow(np.stack([ImageNormalize(hdu[i][0].data,interval=ZScaleInterval())(hdu[i][0].data) for i in range(3)], axis=2)) #強調化・合成して画像を表示 
plt.savefig(target + '.jpg') #画像保存
plt.close() #クローズ

天体の天球上の位置は、WCS座標で表すことができます。

4. 結果

感動です。

Power Automate DesktopでCSVファイルをダウンロードしてSQL文を生成してみた

f:id:ri_86:20220322180109p:plain

こんにちは、「ラクして速く」がモットーの辻本です。

このWebサイトに月1でアップされるCSVファイルの情報を、DBに取り込んでください。

そのようなとき、みなさんどうしますか?

CSVファイルのデータ形式がDBと一致しており、新規追加のみであれば、何かツールを使ってDBに取り込むことができるでしょう。

ただ、データが分割されていたり、桁数やフォーマットが違っていたり、DB側で固定値が必要だったり... はたまた、INSERT(追加)ではなく、UPDATE(更新)またはDELETE(削除)の場合は、何かしら加工した上、SQL文を作成して実行する必要があります。

その際、手動でExcelにデータを貼り付けて、加工した上、ごりごりSQL文を作るのはちょっとスマートではないですね。時間もかかります。

そこで登場するのがRPAです。今回はPower Automate Desktopを使ってその作業を完全自動化してみましょう。



【1】フロー完成図

f:id:ri_86:20220317165237p:plain f:id:ri_86:20220317165240p:plain ▲作成するフローの完成図になります。


【2】WebサイトからCSVファイルをダウンロード

f:id:ri_86:20220317182702p:plain ▲今回は「レコーダ」を使用し、WEBサイトからCSVをダウンロードするフローを作成します。

f:id:ri_86:20220323123422p:plain ▲上図のようにWEBサイトのダウンロードボタンを押下する処理をレコーダーで追加します。

f:id:ri_86:20220316170659p:plain ▲ダウンロードしたCSVファイルの中身です。


【3】Excel の起動

f:id:ri_86:20220317142915p:plainExcelカテゴリの中にあるExcel の起動」アクションを追加します。

f:id:ri_86:20220317150759p:plain「ドキュメントパス」は【2】でダウンロードしたCSVを指定してください。


【4】Excel ワークシートから最初の空の列や行を取得

f:id:ri_86:20220317144031p:plainExcelカテゴリの中にあるExcel ワークシートから最初の空の列や行を取得」アクションを追加します。

f:id:ri_86:20220317151059p:plainExcelインスタンスは【3】で作成された変数「ExcelInstance」を指定します。

Excel ワークシートから最初の空の列や行を取得」についてですが、
取得したCSVのデータのある最後の行数・列数の+1を取得するアクションです。
今回の場合、下記のように取得できます。
FirstFreeColumn = E すなわち 5
FirstFreeRow = 6

f:id:ri_86:20220317154104p:plain


【5】Loop処理を追加

f:id:ri_86:20220317170630p:plain「ループ」カテゴリの中にある「Loop」アクションを追加します。
「End」アクションは「Loop」アクションを追加すると自動で追加されます。

f:id:ri_86:20220317160536p:plain ▲「終了」についてですがFirstFreeRow = 6 なので
6 - 1 = 5 となり、5回ループすることになります。


【6】Excel ワークシートに書き込み

f:id:ri_86:20220317170624p:plainExcelカテゴリの中にあるExcel ワークシートに書き込み」アクションを追加します。

ループの中にこのアクションを設定することにより、Excel ワークシートに書き込み」アクションをループさせることができます。

f:id:ri_86:20220317160527p:plain

Excelインスタンスは【3】で作成された変数「ExcelInstance」を指定します。

「書き込む値」についてですが、作成するSQLクエリやDBの構成によって変更してください。 今回はエクセルの参照機能を使用し、INSERT文を作成しています。
また文字列の中に「%LoopIndex%」を使用することでループのたびに1,2,3,4,5と値を設定することができます。

「書き込みモード」は「指定したセル上」

「列」「行」は書き込みたいセルを設定する箇所になります。
今回は F 列の1行目、F 列の2行目...と書き込みたいので
「列」= 「F」
「行」= 「%LoopIndex%」
と指定しています。

書き込みイメージ

Loop1回目

="INSERT INTO user (id, login_id, user_name, user_type)VALUES('"&A1&"','"B1&"','"&C1&"','"D1"');"
Loop2回目
="INSERT INTO user (id, login_id, user_name, user_type)VALUES('"&A2&"','"B2&"','"&C2&"','"D2"');"
...

Excel書き込み後の文字列イメージ

Loop1回目

INSERT INTO user (id, login_id, user_name, user_type)VALUES('1','satou','佐藤','2');
Loop2回目
INSERT INTO user (id, login_id, user_name, user_type)VALUES('2','suzuki','鈴木','2');
...


【7】Excel ワークシートから読み取り

f:id:ri_86:20220317170641p:plainExcelカテゴリの中にあるExcel ワークシートから読み取り」アクションを追加します。

f:id:ri_86:20220317175914p:plain Excelインスタンスは【3】で作成された変数「ExcelInstance」を指定します。

「取得」は「単一セルの値」

「先頭列」「先頭行」は読み取りたいセルを設定する箇所になります。
【6】と同じように F 列の1行目、F 列の2行目...と書き込みたいので
「先頭列」= 「F」
「先頭行」= 「%LoopIndex%」
と指定しています。

読み取りイメージ

Loop1回目

INSERT INTO user (id, login_id, user_name, user_type)VALUES('1','satou','佐藤','2');
Loop2回目
INSERT INTO user (id, login_id, user_name, user_type)VALUES('2','suzuki','鈴木','2');
...

【8】テキストをファイルに書き込みます

f:id:ri_86:20220317170647p:plain「ファイル」カテゴリの中にある「テキストをファイルに書き込みます」アクションを追加します。
f:id:ri_86:20220317160546p:plain「ファイルパス」は作成したい場所に追加してください。
※ファイルパス先にファイルが無い場合は新規でファイルが作成されます。

「書き込むテキスト」は【7】で作成された変数「%ExcelData%」を指定します。

「ファイルが存在する場合」は「内容を追加する」にします。


【9】Excel を閉じる

f:id:ri_86:20220317170636p:plainExcelカテゴリの中にあるExcel を閉じる」アクションを追加します。

f:id:ri_86:20220317160011p:plain ▲ドキュメントパスは【3】で作成された変数「ExcelInstance」を指定します。


【10】作成されたSQLファイルを確認

f:id:ri_86:20220317155803p:plain ▲完成したSQLファイルです。
問題なくクエリが作成されていますね。


【11】最後に

最後まで読んでいただきありがとうございました。
重要なことに時間をかけて、その他のことはできるだけ自動化していきましょう。

その作業、自動化しませんか?

人工衛星軌道アニメーション

週末から暖かい日が続いています。春が近づいていますね!

今回は、「PyEphem」という天文分野のPythonライブラリを使用して、人工衛星軌道をシミュレートし、アニメーション表示してみます。

pyEphemの使い方 〜Pythonで人工衛星軌道をシミュレートする〜 | korintje.com

こちらの記事を参考にさせていただきました。ありがとうございました。

記事の中で

readtleメソッドを使えば、2行軌道要素形式(TLE)のパラメータを読み込むことも出来ます。

との情報もありましたので、TLEパラメータを使用してみます。

LIVE REAL TIME SATELLITE TRACKING AND PREDICTIONS

こちらのサイトで公開されている準天頂衛星システム「みちびき」4号機のTLE情報をパラメータに設定します。

1. モジュールのインポート

import ephem
import matplotlib.pyplot as plt
import os
from datetime import datetime as dt
from datetime import timedelta as td
from matplotlib.animation import ArtistAnimation #アニメーション作成用
from mpl_toolkits.basemap import Basemap #世界地図描画用

matplotlibの「ArtistAnimation」を使うことで、複数の図からアニメーションを作成することができます。

2. TLEパラメータを設定

line1 = 'QZS-4 (MICHIBIKI-4)'
line2 = '1 42965U 17062A   22057.72757807 -.00000328  00000-0  00000-0 0  9995'
line3 = '2 42965  40.7914   3.5343 0749421 269.5117 284.1873  1.00283299 16058'

TLE情報の「42965U」の「U」は、未分類(Unclassified)を意味し、公開されているTLEに付いています。

3. 時刻データを作成

epoch_date = "22057.72757807" 
year = int(epoch_date[:2])
year += 2000
datetime = float(epoch_date[2:])
decimal_time = dt(year, 1, 1) + td(datetime - 1)
time_list = [(decimal_time + td(hours=i/60)).strftime("%Y/%m/%d %H:%M:%S") for i in range(0,3600)]

TLE情報の一つの観測時刻をフォーマット変換します。また、その時刻を起点として3600個の時刻データを作成します。

4. 人工衛星のプロット画像をアニメーション化

images = [] #画像リスト用
fig = plt.figure() #描画領域を作成

m = Basemap() #世界地図を表示
m.drawcoastlines() #海岸線を表示

for time in time_list:
    image = []
    satellite = ephem.readtle(line1, line2, line3) #TLEパラメータを読み込む
    satellite.compute(time) #指定時刻で実行
    latitude = satellite.sublat / ephem.degree #緯度を取得
    longitude = satellite.sublong / ephem.degree #経度を取得
    x,y = m(longitude, latitude) #XY座標を取得
    image += m.plot(x, y, 'bo', markersize=7) #青丸でプロット
    images.append(image) #画像リストに追加

save_dir = "./" #動画の格納先
ani = ArtistAnimation(fig, images, interval=10, repeat=False) #10ミリ秒毎に図を切り替える
ani.save(os.path.join(save_dir,'orbit.mp4')) #動画を格納

5. 作成されたアニメーション

f:id:KenjiU:20220228205224g:plain

「みちびき」の特徴的な軌道である8の字を描いてますね!

【GPU】【YOLO】CUDA cuDNN TensorFlow をWindows10へインストールしてYOLOを動かす

AIチームの大澤です.

AIモデルの学習をする上でGPU環境は欠かせないものですが,構築する上ではCUDA cuDNN Tensorflowなどを環境に合わせて適切なバージョンを入れないと動かなかったりするので大変です.

また,他にもちょっとしたことでインストールが上手く行かなかったりGPUを認識してくれなかったりすることがあるのも厄介なところです. 今回は新しいPCでYOLO v3を動かすためのGPU環境を構築したため,その手順を残しておきたいと思います.

0. まずはじめに

CUDA cuDNN TensorFlowをそれぞれどのバージョンの組み合わせにするのが良いかということですが,それに関しては以下のページに早見表が載っているので,この組み合わせでインストールをするのが良いとのことです.

www.tensorflow.org

今回は以下の組み合わせで導入し,YOLO v3を動かすところまで行いました. またpython環境が整っていないまっさらな状態なので,pythonもインストールしていきます.

  • tensorflow-2.2.0
  • CUDA 10.1
  • cuDNN 7.6
  • Python 3.8

その他情報

  • OS: Windows10 pro
  • GPU: RTX2070 super *1

やることはこちらのとおりです.

  1. NVIDIAドライバをインストール
  2. CUDAをインストール
  3. cuDNNをダウンロード
  4. pythonをインストール
  5. 仮想環境(venv)を作成
  6. tensorflowをインストール
  7. YOLO v3を動かす

1.NVIDIAドライバをインストールする

インストールの前に,次のソフトウェアが入っている場合はアンインストールします.

大体のGPUマシンはゲーミングPC扱いになっており,ゲームに最適な設定でGPUを動かすためにGeForce Experienceというツールが入っているようです.こちらが入っていると,CUDAのインストールが上手く行かない場合があるとのこと. (参考:https://webbigdata.jp/study/post-9499)

ちなみに私の場合はNVIDIA FrameView SDKが見当たらなかったので,それ以外の2つをアンインストールしました.

それではNVIDIAのドライバをダウンロードしてきます.

www.nvidia.co.jp

自身の環境にあったドライバを選択します.私の場合は以下です. ダウンロードタイプはStudioドライバーで良いかと思います.

f:id:kyoshi0000:20220225203019p:plain

f:id:kyoshi0000:20220225203213j:plain

ダウンロードができたら無心でインストールをします.

2.CUDAをインストールする

CUDAをダウンロードします.

developer.nvidia.com

組み合わせ早見表によると10.1を入れる必要があるとのことなので,「CUDA Toolkit 10.1」をクリックします.

「Select Target Platform」は画像のようにしました.

f:id:kyoshi0000:20220225203355j:plain

こちらもダウンロードができたら無心でインストールをします.

3.cuDNNのダウンロード

cuDNNをダウンロードしていきます.今までの中で一番面倒です. というのも,メンバーシップ登録をしないとダウンロードさせてくれないからです.

developer.nvidia.com

Download cuDNN → Join now でメールアドレスを登録をしましょう.

無事にメンバーシップ登録が終わったらログインをし,cuDNNをダウンロードします. 早見表によるとcuDNNは7.6を入れる必要があります.そして今回CUDAは10.1なので, 「Download cuDNN v7.6.0 (May 20, 2019), for CUDA 10.1」をダウンロードしました.

zipファイルになっていると思うので,解凍をします.

解凍されたcudaフォルダには後ほどパスを通すので,参照しやすいところに置いておきたいです.Cドライブ直下にtoolsというフォルダを作り,その中に入れることにします.

f:id:kyoshi0000:20220225203752j:plain

パスの設定

ここでパスの設定を行います.以下の4行を環境変数に追加します.

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\extras\CUPTI\lib64
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\include
C:\tools\cuda\bin

f:id:kyoshi0000:20220225203958j:plain

4.Pythonのインストール

以下のURLからpythonをインストールします. 早見表ではPython3.8が対応しているとのことなので,今回はPython 3.8.8をインストールしました.

http://
https://www.python.org/downloads/

インストールができたら確認のため,コマンドプロンプトpython -Vを実行してみます.
Pythonのバージョンが表示されるはずですが,私は表示されませんでした.

Pathが通ってなさそうなので,以下の2つをシステム環境変数へ追加します.


C:\Users\ユーザー名\AppData\Local\Programs\Python\Python38
C:\Users\ユーザー名\AppData\Local\Programs\Python\Python38\Scripts

f:id:kyoshi0000:20220225204414j:plain

PC再起動後,コマンドプロンプトで再びpython -Vのコマンドを実行.
python 3.8.8と表示されました.これでPythonのインストールは完了です.

5.仮想環境を作成(venv)

python機械学習を行う際には様々なライブラリを使用しますが,そのライブラリのバージョンもプロジェクトによって異なる場合がよくあります.

プロジェクトAはver.1.0で動くけど,プロジェクトBはver.2.0じゃないと動かない」となるのは面倒です. なのでプロジェクト毎に仮想環境を作り,プロジェクトAの仮想環境にはver.1.0を,プロジェクトBの仮想環境にはver.2.0のライブラリを入れてあげればいいよねということで,仮想環境を作成していきます.

公式でサポートされているので簡単です. まず,プロジェクト用のフォルダを作成します.今回はデスクトップにProjectフォルダを作り,その中にYOLOフォルダを作成しました.このYOLOフォルダ内に仮想環境を作成し,今後はその中で作業していきます.

デスクトップ
 └─ Project
    └─ YOLO

コマンドプロンプトを開き,cdコマンドでYOLOフォルダに移動します.

cd C:¥Users¥<ユーザー名>¥Desktop¥Project¥YOLO

ここでpython -m venv envを実行します. YOLOフォルダ内に「env」というフォルダが作成されればOKです.

引き続きコマンドプロンプトenv¥Scripts¥activateを実行すると仮想環境をアクティベートすることができます.deactivateで仮想環境から抜けます.

これでYOLOフォルダ内に仮想環境を作成できました.

再度env¥Scripts¥activateで仮想環境をアクティベートしたらtensorflowを入れていきます.

これ以降は仮想環境を立ち上げた状態で進めていきます.

6.tensorflow v2.2.0をインストール

ではpip install tensorflow==2.2.0でインストールします.

終了したらtensorflowがGPUを認識するか確認をします.

コマンドプロンプトpythonと入力し,対話モードでpythonを実行します. 次に以下の2行を入力します.

import tensorflow as tf
tf.test.is_gpu_available()

出力にTrueと出れば認識できているので,exit()と入力して対話モードを終了します.(参考:https://www.dan-myblog.com/post/52/)

最後にYOLOv3(GPU)の設定を行います.

7.YOLO v3を動かす

ソースファイルのダウンロード

YOLOv3をダウンロードします.git cloneでもzipファイルをダウンロードでもどちらでも構いません.

github.com

ダウンロードしたyolov3-tf2-masterフォルダ以下のファイル群を,上で作成した仮想環境内に配置する.


フォルダ構成
YOLO(仮想環境)
  ├── envフォルダ
  ├── yolov3-tf2-masterの中身一式
  ︙

モデルのダウンロード

こちらからモデルをダウンロードし,dataフォルダに配置します. https://pjreddie.com/media/files/yolov3.weights

以下のコマンドでconvert.pyを実行します.*2


python convert.py --weights ./data/yolov3.weights --output ./checkpoints/yolov3.tf


モデルの変換ができたらYOLOを実行してみます. webカメラで検出を行いたいので,以下のコマンドを入力します.

python detect_video.py --video 0

うまくいっていればこれでYOLOが実行できているはずです. 私もかなり調べながら環境を構築しましたが,もう同じことはしたくないので備忘録も兼ねてこちらに残しておきます.

お疲れさまでした.

*1:ちなみにRTX30*系だとCUDA 11.系しか対応していないそうです.[参考:https://teratail.com/questions/331673]

*2:以下のページのReadMeにコマンドの説明が書いてありますhttps://github.com/zzh8829/yolov3-tf2

座標変換

物事の考え方や捉え方を変えてみると、新しい発想や解決法が得られることがあります。

  • 別の立場の人の視点に立って物事を考えてみる。
  • 他の人のいつもと違う考えや価値観に触れて、別の視点に気付く。

等、ビジネスを取り巻く環境が大きく変化する今日この頃、多様な視点を持つことはとても大事ですね。

さて、今回を視点を変えるということで...
画像の座標変換という手法を試してみます。

世界地図と地球儀で、大陸や島の大きさがそれぞれで違うと感じたことはないでしょうか?
メルカトル図法の地図は、楕円体である地球を円筒で表現している(緯線はすべて赤道と同じ長さになる)ので、北極や南極に近づくほど実際の面積よりも大きく表示されてしまいます。

matplotlibとMayaviでNASAの画像を『地球儀』にしてみた。 - プログラム日記φ(..)

こちらの記事でご紹介されているように

 x = r \sinθ \cosφ
 y = r \sinθ \sinφ
 z = r \cosθ

球面座標 (動径r, 緯度θ, 経度φ)

直交直線座標 (x, y, z)
へ変換することで、地図の各緯度経度の値を球面にマッピングし、地球儀を作成することができます。

ついでに
mplot3d API — Matplotlib 2.0.2 documentation

view_init(elev=None, azim=None)
# elev: z軸方向から見た仰角
# azim: x, y軸方向の方位角

この関数を使用し、azimの値を0〜360の間で変化させて、地球儀を回転させてみます。 f:id:KenjiU:20220130235421g:plain 地図ではなく、写真を球面にマッピングすると以下のようになります。 f:id:KenjiU:20220130235447g:plain 目が回りそうです。
座標変換ですが、AIで画像解析する際の前処理の一つとして使うこともあります。また別の機会にご紹介しますね。