[Python 3.8.0] S3に画像をアップロード・ダウンロードする

### S3へupload
1.まず送信したい画像を用意します。SVMで使用したgeorgia.jpgを使いましょう。

2.AWSコンソールにログインし、S3からbucketを作成します。
取り敢えず、hanbai-raspi としておきます。

画像の送受信のみに利用する為、Block all public accessにします。

3.AmazonS3FullAccessのユーザを作成

4.ubuntu側でAWS SDKのboto3をインストール
$ pip -V
pip 20.1.1 from /home/vagrant/.local/lib/python3.8/site-packages/pip (python 3.8)
$ pip install boto3

import boto3

accesskey = "****"
secretkey = "****"
region = "ap-northeast-1"

s3 = boto3.client('s3', aws_access_key_id=accesskey, aws_secret_access_key= secretkey, region_name=region)

filename = "georgia.jpg"
bucket_name = "hanbai-raspi"

s3.upload_file(filename,bucket_name,filename)
print("upload {0}".format(filename))

$ python app.py
upload georgia.jpg

はい、アップロードできてます。

続いて、downloadもやっちゃいましょう。

### download

import boto3

accesskey = "****"
secretkey = "****"
region = "ap-northeast-1"

s3 = boto3.resource('s3', aws_access_key_id=accesskey, aws_secret_access_key= secretkey, region_name=region)

bucket = s3.Bucket("hanbai-raspi")
filename="georgia.jpg"
path="img/georgia.jpg"


bucket.download_file(filename,path)
print("upload {0}".format(filename))

アップロードとダウンロードだと書き方が若干異なるので注意が必要ですね。
さあ、続いて、ubuntuとラズパイ4でcronの実行の仕方。

[RaspberryPi 4] カメラモジュールの起動手順

RaspberryPi 3 model B+ を持っていましたが、カメラモジュールを差し込んだ途端、電源はつくがHDMIでモニターにシグナルが送れなくなってしまったので、RaspberryPi 4を買い直すことにした。

1) 秋葉原の秋月電子通商で「RaspberryPi 4」と「ラズパイ4用の電源アダプター」を購入
2) ラズパイnoobsからsdカード(32GB)にdownload
https://www.raspberrypi.org/downloads/noobs/
3) sdカードをRaspberryPi 4に差し込んで、Rasbianをインストール
4) 「設定」->「Raspberry Piの設定」->「インターフェイス」->「カメラ」->「有効」
5) コマンドライン
$ vcgencmd get_camera
supported=1 detected=1

$ sudo raspistill -o image.jpg
/home/pi/image.jpg

来た!
RaspberryPi3のNo Signalの原因が不明で、もしからたモニターに原因があるのでは?と思って、実はモニター(6000円位)も買い直してしまったorz… モニターは必要なかった。。。。
何れにしても、カメラモジュールはクリア!
さー次はcron x python作るぞー

[OpenCV4.5.0] 画像をランダムフォレストで学習して判定したい3 ~ 判定

学習データを coffee.pkl に保存します。

clf = RandomForestClassifier()
clf.fit(x_train, y_train)

joblib.dump(clf, 'coffee.pkl')

学習データの画像とは別に判定したいターゲット画像を用意します。

fire_11.jpg

black_11.jpg

georgia_11.jpg

学習データを作ったように同じようリサイズ、リシェイプして判定(predict)します。

import cv2
import joblib

def predict_coffee(filename):
	clf = joblib.load("coffee.pkl")

	path = "img/target/"
	img = cv2.imread(path + filename)
	img = cv2.resize(img, (48, 64))
	img = img.reshape((-1, 9216))
	res = clf.predict(img)

	if res[0] == 0:
		print(filename + " = BLACK無糖")
	elif res[0] == 1:
		print(filename + " = FIRE微糖")
	else:
		print(filename + " = Georgia blend")
	

predict_coffee("black_11.jpg")
predict_coffee("fire_11.jpg")
predict_coffee("georgia_11.jpg")

$ python3 app.py
black_11.jpg = BLACK無糖
fire_11.jpg = FIRE微糖
georgia_11.jpg = Georgia blend

やば。。。。
blackに関しては、”Black”の文字ないのに判定できちゃうんだ。。。

ちょっと人生頑張ってみるわ。。

[OpenCV4.5.0] 画像をランダムフォレストで学習して判定したい2 ~学習

画像を用意済み。

画像サイズは864x1152pxなので、(48, 64)にします。
データラベルは、FIRE微糖=0、Georgia blend=1、BLACK無糖=2 とします。
リサイズして、一次元に展開して配列に入れる。

import cv2
import os, glob
import joblib

from sklearn.model_selection import train_test_split
from sklearn import datasets, metrics
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score


image_size = (48, 64) # 864:1152(3:4)の画像の為
path_black = "img/black"
path_fire = "img/fire"
path_georgia = "img/georgia"

x = [] # 画像
y = [] # ラベル

def read_dir(path, label):
	files = glob.glob(path + "/*.jpg")
	for f in files:
		img = cv2.imread(f)
		img = cv2.resize(img, image_size)
		img_data = img.reshape(-1, )
		x.append(img_data)
		y.append(label)

read_dir(path_black, 0)
read_dir(path_fire, 1)
read_dir(path_georgia, 2)

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2)

clf = RandomForestClassifier()
clf.fit(x_train, y_train)

y_pred = clf.predict(x_test)
print(accuracy_score(y_test, y_pred))

6回テストしてaccuracy_scoreはこんな感じ。平均して91%くらい。
$ python3 app.py
0.8333333333333334
$ python3 app.py
1.0
$ python3 app.py
1.0
$ python3 app.py
1.0
$ python3 app.py
0.6666666666666666
$ python3 app.py
1.0

91%の精度ってどうなんだろう。画像を取る角度を一定にすれば、もっと精度は上がりそうな気がする。

[OpenCV4.5.0] 画像をランダムフォレストで学習して判定したい1 ~写真の用意

まず画像の用意から。
缶コーヒーで(1)FIRE微糖、(2)Georgia blend、(3)BLACK無糖を用意する。

続いて、各缶コーヒーの写真を取る。取り敢えず、10枚ずつ位。
(1)FIRE微糖

(2)Georgia blend

(3)BLACK無糖

どの写真がどの缶コーヒーかラベリングをしたいので、画像の名前を変更する。
fireは fire_${i}.jpg、 Georgia blendは georgia_${i}.jpg、BLACK無糖は black_${i}.jpgにする。

centos8
imgフォルダの中にblack, fire, georgiaフォルダを作成し、その中にそれぞれの画像を入れる。

続いて、これらの画像を学習していきます。

[AWS] IAMでユーザのEC2操作権限を制御したい

まずユーザ作成

続いて、set permissionsでcreate policy
sidはユニークであればなんでも良い。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "ec2:Describe*",
      ],
      "Sid": "Stmt1373379895000",
      "Resource": "*"
      "Effect": "Allow"
    },
    {
      "Action": [
        "ec2:StartInstances",
        "ec2:RebootInstances",
        "ec2:StopInstances",
      ],
      "Sid": "Stmt1373378552000",
      "Resource": [
        "arn:aws:ec2:ap-northeast-1:${account_id}:instance/${instance_id}"
      ],
      "Effect": "Allow"
    }
  ]
}

ec2:Describe*は、リソースレベルで管理できない。
よって、リージョンを変えるか、AWSアカウントを変えるしかない。

どういう風に制御しているのか理解できれば、間接的にセキュリティ方針を俯瞰して観れるようになりますね。

[AWS] Route53でSTG用サブドメインの設定をしたい

### 前提
– 既にお名前.comで取得したドメインをRoute53で割り当てている
– ACMで証明書を発行し、HTTP/HTTPSのinbound rule設定済み

### やりたいこと
– STG用に、商用ドメインの前に「stg.${domain}」としてサブドメインを使いたい
eg. http://stg.hoge.com

色々試した結果、上手くいく方法がわかった。

### 手順
1. EIPの作成
EC2 -> Elastic IPs -> Allocate Elastic IP addressで、EIPを作成し、Associate Elastic IP addressで、STGのインスタンスに紐づける。

2. Route53でサブドメイン用のHosted Zoneの作成
Route53 -> Hosted Zone -> Create hosted zone で Domain nameに stg.${domain}で hosted zoneを新規に作成する。
すると、NSレコード4つとSOAが作られる。※AレコードのEIPは後で追加したもの。

3. NSレコード4つをお名前.comの対象のドメインのDNS設定で追加する。ホスト名は「stg」で、タイプは「NS」、Valueは上記で作られた値
※お名前.com側はこれで終わり

4. サブドメインのHosted ZoneにEIPを追加
create recordでrecord nameはnull、ValueにEIP、Record TypeはAを選択して、EIPを設定

5. 上記で作られた4のNSレコードを、商用ドメイン側のHosted zoneにも追加する。

6. ブラウザから stg.${domain} にアクセスして疎通確認

さードキュメント作るぞーーーーーーーーーーーーーーーー

[AWS] bastionサーバからprivate route tableへのSSHログインの方法 [ドハマり]

まず、public route table (public subnet割り当て)と private route table(private subnet割り当て) を作ります。

public route table
– internet gatewayを割り当てています。

private route table
– 後でnat gatewayを割り当て

private subnetに配置しているEC2のセキュリティグループのインバウンドルール
-> sshのルールで、bastion serverの ${private IPv4 ip}/32 を設定する

### ローカルからbastionにssh
$ ssh ec2-user@${basionserverのpublic ip} -i ~/.ssh/*.pem

そして、bastionサーバにログインし、/.sshに 秘密鍵(*.pem)を配置する

### bastionからprivate subnetのec2にログイン
$ ssh -i .ssh/*.pem ec2-user@${bastionserverのprivate ip}

すごいハマった。3時間ぐらい。
ローカルからはpublic ipでsshログインするけど、bationからはprivate IPv4 ipでログインする
これ違い理解してないと、なんでログインできないか永遠にわからなかったわ

[OpenCV4.5.0] 画像の差分を抽出

2つ画像を用意します。
※プロントで作業しています。ワイヤレスマウスUBS

import cv2
import numpy as np

img_last = cv2.imread(“a.jpg”)
img_last = cv2.cvtColor(img_last, cv2.COLOR_BGR2GRAY) # 白黒化
img_last = cv2.GaussianBlur(img_last, (9, 9), 0) # ぼかし
img_last = cv2.threshold(img_last, 100, 255, cv2.THRESH_BINARY)[1] # 画像の二値化

img = cv2.imread(“b.jpg”)
img_current = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_current = cv2.GaussianBlur(img_current, (9, 9), 0)
img_current = cv2.threshold(img_current, 100, 255, cv2.THRESH_BINARY)[1]

img_diff = cv2.absdiff(img_last, img_current)
cnts = cv2.findContours(img_diff, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]

for pt in cnts:
x, y, w, h = cv2.boundingRect(pt)
if w < 30: continue cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) cv2.imwrite("result.png", img) [/python]

OK, Let’s Gooooooooooooooooooooo

[OpenCV4.5.0]NumPyを使って赤色のみ抽出

import cv2
import numpy as np

img = cv2.imread("rose.jpg")

img[:, :, 0] = 0
img[:, :, 1] = 0

cv2.imwrite("result.png", img)

before

after

### HSVで赤っぽい部分の輪郭を表示

import cv2
import numpy as np

img = cv2.imread("rose.jpg")

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV_FULL)
h = hsv[:, :, 0]
s = hsv[:, :, 1]
v = hsv[:, :, 2]

img2 = np.zeros(h.shape, dtype=np.uint8)
img2[(h > 200)  & (s > 100)] = 255

cv2.imwrite("result.png", img2)

ほう