Briswell Tech Blog

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

大門・浜松町を3D化

PLATEAUの3D都市データについて、弊社のオフィスがある大門・浜松町(三次メッシュコード:53393680)がLOD2(屋根形状があるモデル)にて公開されているということで確認してみます。

ピンク部分がLOD2整備範囲

3D都市モデル(Project PLATEAU)東京都23区 - データセット

東京都23区の3D都市データ(商用利用可能)はこちらよりダウンロードできます。

さて、CityGML、3D Tiles、GeoJson、MVT、Shape、FBX、OBJ、GeoTIFF...
と色々ファイル形式がありますが、どれを利用するか。
地理空間や3D関連のファイルは種類が多いですね。

今回はBlenderオープンソースの3DCGソフト)でインポートできる以下のFBXファイルを利用します。

  1. 建物モデル:13100_tokyo23-ku_2020_fbx_3_op > bldg > lod2 > 53393680_bldg_6677.fbx

  2. 橋梁モデル:13100_tokyo23-ku_2020_fbx_3_op > brid > 53393680_brid_6677.fbx

【blender】リアルな都市の作り方!(~PLATEAUを用いる方法~)(ボイスピーク 解説) - YouTube

こちらの動画を参考にさせていただき、Blenderで大門・浜松町の3D都市を作成しました。地面、背景、光源の設定や、建物のテクスチャ(色や質感)変更等、大変勉強になりました。ありがとうございます。

MacBook Pro(M1 Proチップ)で作業していたのですが、なかなか画像が出力(レンダリング)されず、調べていたところ...
なんとBlenderでM1 Macレンダリングが最適化される設定がありました。

この設定により、無事にレンダリングすることができました。

結果(赤の矢印が弊社のオフィスがあるビルです)

すごいですね。このようなオープンデータから価値を生み出していきたいです。

高精度音声認識モデル「Whisper」に文字起こしさせてみる

AI,IoT担当の大澤です。 OpenAIが「Whisper」というすごい音声認識モデルを開発したと盛り上がっていたので、どんなものなのかと思って試してみました。 文章生成の「GPT-3」、画像生成の「DALL・E 2」など、OpenAIは高性能なAIを開発してきているので今回も楽しみです。

結論から言うとめちゃめちゃ簡単に精度の高い文字起こしができました。GoogleColabを使用したので、以下にその手順を記載します。

1. 準備

GoogleDrive内に適当な作業フォルダを作ります。今回は「Whisper」フォルダにしました。 (私の環境では「マイドライブ>Colab Notebooks>whisper」というパスになってます)

作ったフォルダ内でもう一度「新規」のボタンを押し、今度は「その他」を選択すると以下のようなツリーが表示されます。

ここで「GoogleColaboratory」が表示されていればいいですが、ない人は「新規」→「その他」→「アプリを追加」で「colaboratory」と検索して追加しておきましょう。

GoogleColaboratory
GoogleColabを追加
追加されれば先程のツリーに表示されているはずですので、クリックして新規ファイルを作成します。

新規ファイル

2. 設定

まずはcolabの設定をしましょう。タブの「ランタイム」から「ランタイムタイプを変更」を選択し、以下のようにGPUに変更します。

ランタイムのタイプを変更
GPUに設定

次に文字起こしをするデータを用意しましょう。 動画データ(mp4,movなど)でも音声データ(mp3,wavなど)でも使用することができます。 私の方では「output.mp4」という動画を用意しました。 この動画データを先程準備したGoogleDrive内の「whisper」フォルダにアップロードしておきましょう。

output2.mp4もありますが気にしないでください

ついでにColabノートブックの名前をwhisper.ipynbに変えました。

3. コード

それではコードを書いていきます。たったの数行です。

# githubからインストール
!pip install git+https://github.com/openai/whisper.git

# whisperのインポート
import whisper

# mediumモデルを使用
model = whisper.load_model("medium")

# 推論
result = model.transcribe("/content/drive/MyDrive/Colab Notebooks/whisper/output.mp4")
print(result["text"])

# 結果をテーブル表示で見る
import pandas as pd
pd.DataFrame(result["segments"])[["id", "start", "end", "text"]]

セルを細かく区切りました。

ちなみにcolabにはセルというものがあり、このセル単位でコードを実行することができます。 一つのセルの中に全文書くこともできますが、出力を確認しながら進められるようにいくつかに区切って書いたほうが良いです。

4. 実行

それでは実行してみましょう。

タブの「ランタイム」→「すべてのセルを実行」で一気に実行できます。 ちなみにセル単位で実行するにはセルの左の再生マークを押すと、そのセルを実行できます。(Shift + Enterでもいけます)

また、おそらくGoogleDriveがマウントされている(連携されている)状態だと思いますが、されていない場合はアラートが出るので、指示に従って連携しましょう。

実行結果がこちらです。

ちなみに私はこちらの動画を使ってみました。

www.youtube.com

日本語でもかなりの精度で認識されていますね。

また、検出した動画時間も出力されるので、字幕を簡単につけることができそうです。 会議の議事録動画をとりあえず文字起こししておけば、あとからテキスト検索できてしかも動画内での該当箇所も簡単にわかるということですね。らくちんです。

5. まとめ

非常に簡単に実行できたかと思います。

今回はmediumモデルで実行しましたが、より精度の高いlargeも使うことができます。その代わりに時間がかかりますし、最悪メモリ不足で実行できない場合があるかも知れません。

2分半の動画ではmediumで1分、largeで2分近くかかっていたと思います。気になる方はセルの3行目を「large」に変えて試してみても良いと思います。

この精度の文字起こしがオープンソースで公開されているのはすごいですね。 それでは。

Elastic Beanstalk のエラー

暑い日々が続いておりますね。
みなさま、いかがお過ごしでしょうか。

今回はElastic Beanstalk(以下EBと記載します) のサポート対象から Node.js 12 が消滅するので、16にあげる作業を行った際に、よくわからないエラーにぶち当たったので、備忘録含め、記載します。


Node.js 12 running on 64bit Amazon Linux 2 から
Node.js 16 running on 64bit Amazon Linux 2 にアップデートを行おうと、少し調整を入れ、Circle CIからEBへデプロイをかけたところ、

CIエラー

ERROR: TimeoutError - The EB CLI timed out after 10 minute(s). The operation might still be running. To keep viewing events, run 'eb events -f'. To set timeout duration, use '--timeout MINUTES'.

タイプアウトでデプロイが失敗しました。
ログを出力してみると何も出ていない...

よくわからないので、ダメ元で再度CIを実行しました。

CIエラー2

2022-08-22 04:12:40 ERROR Instance deployment: 'npm' failed to install dependencies that you defined in 'package.json'. For details, see 'eb-engine.log'. The deployment failed.
2022-08-22 04:12:40 ERROR Instance deployment failed. For details, see 'eb-engine.log'.
2022-08-22 04:12:41 ERROR [Instance: i-0b7da73e780dfead2] Command failed on instance. Return code: 1 Output: Engine execution has encountered an error..
2022-08-22 04:12:41 INFO Command execution completed on all instances. Summary: [Successful: 0, Failed: 1].
2022-08-22 04:12:41 ERROR Unsuccessful command execution on instance id(s) 'i-0b7da73e780dfead2'. Aborting the operation.
2022-08-22 04:12:41 ERROR Failed to deploy application.



今度はエラーが出ていたので、詳細確認のため、ログを見てみると

2022/08/22 04:12:40.550548 [ERROR] An error occurred during execution of command [app-deploy] - [Use NPM to install dependencies]. Stop running the command. Error: Command /bin/sh -c npm --production install failed with error signal: killed. Stderr:npm WARN config production Use --omit=dev instead.

2022/08/22 04:12:40.550567 [INFO] Executing cleanup logic

2022/08/22 04:12:40.615852 [INFO] CommandService Response: {"status":"FAILURE","api_version":"1.0","results":[{"status":"FAILURE","msg":"Engine execution has encountered an error.","returncode":1,"events":[{"msg":"Instance deployment: 'npm' failed to install dependencies that you defined in 'package.json'. For details, see 'eb-engine.log'. The deployment failed.","timestamp":1661141560538,"severity":"ERROR"},{"msg":"Instance deployment failed. For details, see 'eb-engine.log'.","timestamp":1661141560558,"severity":"ERROR"}]}]}



このようなログが吐き出されていました。
Local で
npm --production install

を実行してもエラーは起こりませんでした。

少しGoogle先生に質問をしたところ、

stackoverflow.com

この記載を見つけました。
インスタンスのスペックが低すぎるのが原因ではないか。
確かに上記エラーが発生したEBのスペックは t3.micro でした。

藁にも縋る気持ちで、t3.medium に更新を行い、再度チャレンジしました...

結果は成功。


ログだけ見てもよくわからない系のエラーは悩ましいですね。解決できてよかったです。

Pythonで3D地形図化

弊社のオフィスのある芝大門は、江戸時代より増上寺門前町として多くの商店もあり賑わっています。以前、ご紹介しましたが江戸の大名屋敷もすぐそばにありました。戻れるものならこの目で見てみたいものです。

このあたりは、江戸時代に埋め立てがされ、それ以前は海の下(日比谷入江)だったようです。
国土地理院標高タイルの数値データより3D地形図を作成し、その事実を探っていきたいと思います。

matplotlibで国土地理院標高タイルから3D地形図を描いてみる - プログラム日記φ(..)

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

では、行って参る。

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

よく使われるモジュールですね。

import pandas as pd #csvファイル読み取り用
import requests #HTTP通信用
import numpy as np #数値計算用
import matplotlib.pyplot as plt #グラフ作成用
from io import StringIO #文字列をファイルのように扱える

2. 標高データの読込

こちら国土地理院標高タイルについて、芝大門周辺の4つのタイルを取得します。

url_1 = 'http://cyberjapandata.gsi.go.jp/xyz/dem/13/7276/3226.txt' #芝大門を含むタイルNo.1
url_2 = 'http://cyberjapandata.gsi.go.jp/xyz/dem/13/7275/3226.txt' #西側のタイルNo.2
url_3 = 'http://cyberjapandata.gsi.go.jp/xyz/dem/13/7276/3227.txt' #南側のタイルNo.3
url_4 = 'http://cyberjapandata.gsi.go.jp/xyz/dem/13/7275/3227.txt' #南西側のタイルNo.4

urlList = [url_1, url_2, url_3, url_4]
z_result = []

for url in urlList:
  response = requests.get(url)
  maptxt = str.replace(response.text, u'e', u'-0.0')
  Z = pd.read_csv(StringIO(maptxt), header=None)
  z_result.append(Z)

3. 標高データを結合

読み込んだ4つのタイルの標高データを結合します。

z1 = np.concatenate((z_result[1],z_result[0]), axis = 1) #No.1とNo.2を結合
z2 = np.concatenate((z_result[3],z_result[2]), axis = 1) #No.3とNo.4を結合 

z_mix = np.concatenate((z1,z2), axis = 0) #No.1&2とNo.3&4を結合

4. 3Dグラフの設定

3Dグラフのデザイン部分です。

X, Y = np.meshgrid(np.linspace(0,255,512), np.linspace(255,0,512))
fig = plt.figure(figsize=(10, 8), dpi=80, facecolor='w', edgecolor='k') #w:白(White), k:黒 (Black)
ax = fig.gca(projection='3d') #3Dグラフ
ax.set_aspect('auto') #Axes3D currently only supports the aspect argument 'auto'.
ax.view_init(84, -67.5) #視点の設定

5. 3Dグラフを描画

標高値に応じて曲面を描きます。また、弊社のオフィス位置あたりに★を出力します。

surf = ax.plot_surface(X, Y, z_mix, cstride=1, rstride=1, cmap='rainbow', antialiased=False)
ax.text(140, 195, 2, "★", 'z', color='white', size='xx-large')
cb = plt.colorbar(surf, shrink=0.5, aspect=10)

6. 3Dグラフを保存

さて、どうでしょうか。

plt.savefig('mix_map.jpg')

7. 結果

江戸の見晴らしの名所と言われた愛宕山や、芝公園辺りから標高が高くなっているのが確認できますね。

Pythonで旅する東海道五十三次

東海道五十三次のルートは、日本橋(江戸)〜三条大橋(京)の全長約490kmの街道です。

江戸時代の人は、徒歩で約二週間かけて旅していたとのこと。一日の移動距離は平均すると35km(一歩が70cmとすると5万歩)となります。すごいですね。

私もその昔、東海道五十三次を自転車でトライしたのですが、小田原〜箱根間で転倒し、箱根の坂を前に挫折しました。

今回、Pythonで再チャレンジしたいと思います。

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

import folium #地図作成用
from folium.features import DivIcon #文字列表示用
from folium import plugins #機能拡張用

2. 東海道五十三次の宿場を定義

shukuba_list = \
[['日本橋',139.774444444444,35.6836111111111], 
['品川宿',139.739166666667,35.6219444444444], 
['川崎宿',139.707777777778,35.5355555555556], 
['神奈川宿',139.632277777778,35.4727777777778], 
['保ヶ谷宿',139.595555555556,35.4440277777778],
['戸塚宿',139.529861111111,35.3950277777778], 
['藤沢宿',139.486305555556,35.3456666666667], 
['平塚宿',139.337805555556,35.3272777777778], 
['大磯宿',139.315305555556,35.309],
['小田原宿',139.161027777778,35.2487222222222], 
['箱根宿',139.026361111111,35.1904166666667], 
['三島宿',138.914472222222,35.11925], 
# 40宿場省略
['草津宿',135.960638888889,35.0174444444444], 
['大津宿',135.861416666667,35.0059722222222], 
['三条大橋',135.774361111111,35.0103333333333]]

※緯度・経度の引用元
東海道五十三次 - Wikipedia

3. 地図を作成

tokaido_map = folium.Map(location=[35.360626, 138.727363], zoom_start=8, tiles='stamenterrain') #富士山の座標を中心に地図を作成

for i in range(len(shukuba_list)):
    length=len(shukuba_list[i][0]) #宿場名の文字数を取得 
    if i == 0 or i == 54: #始点と終点は★を表示
        folium.Marker(location=[shukuba_list[i][2], shukuba_list[i][1]], icon=DivIcon(
            icon_size=(25, 25),
            icon_anchor=(0, 0),
            html='<div style="text-align: center; font-size: 11pt; color : black width: 25px; height: 25px; background: skyblue; border:2px solid #666; border-radius: 50%; ">'+"★"+'</div>'),
            popup=shukuba_list[i][0]+(' '*length)).add_to(tokaido_map) #全角スペースを入れないとポップアップの文字が改行されてしまう
    else: #始点と終点以外は宿場順を表示
        folium.Marker(location=[shukuba_list[i][2], shukuba_list[i][1]], icon=DivIcon(
            icon_size=(25, 25),
            icon_anchor=(0, 0),
            html='<div style="text-align: center; font-size: 11pt; color : black width: 25px; height: 25px; background: skyblue; border:2px solid #666; border-radius: 50%; ">'+str(i)+'</div>'),
            popup=str(i)+'.'+shukuba_list[i][0]+(' '*(length+1))).add_to(tokaido_map) #宿場名をポップアップ表示

4. フルスクリーン機能を追加

plugins.Fullscreen(
    position="topright",
    title="拡大する",      
    title_cancel="元に戻す",
    force_separate_button=True,
).add_to(tokaido_map)

5. HTMLに保存

tokaido_map.save("tokaido-53.html")

結果

自分の足で箱根越えをしたいですね。

File:NDL-DC 1309891-Utagawa Hiroshige-東海道五拾三次 吉原・左富士-crd.jpg - Wikimedia Commons

また、こちらの浮世絵に描かれているように、13.原宿〜14.吉原宿の間で左側に富士山が見える場所があります。箱根越えの後の楽しみです。

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

こんにちは.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 へのバージョンアップも無事行えました!!

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

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