Google cloud vision API サンプル

Google cloud vision API サンプル

https://nikkie-ftnext.hatenablog.com/entry/ocr-with-google-vision-api-python-first-step
によれば

Vision APIのOCRには2つあり
* TEXT_DETECTION
* DOCUMENT_TEXT_DETECTION
の2つがある

リファレンスは
https://cloud.google.com/vision/docs/ocr?hl=ja#optical_character_recognition_ocr
TEXT_DETECTION
任意の画像からテキストを検出、抽出します。
たとえば、写真に道路名や交通標識が写っていれば、
抽出された文字列全体、個々の単語、それらの境界ボックスが JSON レスポンスに含まれます。

DOCUMENT_TEXT_DETECTION
画像からテキストを抽出しますが、
高密度のテキストやドキュメントに応じてレスポンスが最適化され、
ページ、ブロック、段落、単語、改行の情報が JSON に含まれます

手書き入力の抽出とファイル(PDF / TIFF)からのテキスト抽出については、DOCUMENT_TEXT_DETECTION をご覧ください

とのこと

コードのサンプルについては
https://cloud.google.com/vision/product-search/docs/samples?hl=ja
にある

とりあえずまず動くか試したいので
2023-03-16【GCP/Python】Vision APIのOCR(光学文字認識)でテキスト抽出!
を参考に動かす

ファイル名を

vision_api_test.py

とする

cd aw10s
cd store_adversting_list 
vim vision_api_test.py


まずは
JSONを任意の場所に置いて読み込むらしいが
情報が古い

この時に認証関連のコマンドを使ってない
2024-01-03GoogleのVision APIをPythonから呼び出して、画像内のテキストを検出する

を参考に
とりあえず

from google.cloud import vision

client = vision.ImageAnnotatorClient()

with open("kanji.png", "rb") as fb:
    content = fb.read()

image = vision.Image(content=content)

response = client.document_text_detection(image=image)
texts = response.text_annotations
print(texts[0].description)

のファイルパスを変えて実行してみる

from google.cloud import vision

client = vision.ImageAnnotatorClient()

with open("test.jpg", "rb") as fb:
    content = fb.read()

image = vision.Image(content=content)

response = client.document_text_detection(image=image)
texts = response.text_annotations
print(texts[0].description)

スマホで撮影したチラシの画像でテスト

実行結果が大量になりそうなので

python vision_api_test.py >> result.txt

でテキストファイルに格納する

結果は

Aグループ版 オモテ
コミュニティー
15
魚担当
おすすめ
16
日
握りのセット!
うなぎの太巻、押寿司
では、うなぎ
―んびょうきゅうりそうなぎの
た
いて
今ぎをのせました。
→サイズ
1208195
うなぎ 28
うなぎ
うなぎり
醬
27.
水公園
coop
ユーコープ
いつもの商品を
膀胱! わくわく 日替りセール!!
お求めやすく!!」
7/100
7/110
7/100
14日
お一家族様
合わせて2点限り
14日
乾
麺10
店頭では10%引の価格を表示しています。
加工食品コーナーの商品に限ります。
※一部対象外の商品がございます。
魚
大
冷凍食品 20
●アイスクリームなど一部対象外商品があります。
詳しくは店頭でご確認ください。
例えばこちらの商品も20%引でこの
7/12 (金
7/13 土
毎週水曜日は
牛乳の日
毎週木曜日は
たまごの日
写真は全てイメージです。
毎週金曜日は
パンの日
コーブ牛乳
お一家族様5点限り
お一家族様 たまご
CO-OP コープ牛乳
1点限り
10個入
パスコ 超熟食パン
静岡県産など
金目鯛切身
切 1パック
680
味つき
734分
えだまめ
超
・6枚
8枚
熟
138円)
刺身用かつお
11バッグ ¥429円
宮格率から 398円 なども
真あじ
128
茶豆
税込
xg 138円
89
参考税込 149 円
天候などにより、水揚げのない場合はご容赦ください。
※写真はイメージです
写真は全てイメージです
新潟県などの国内産
ぶなしめじ 128円
(Wバック)
1袋
税込138円
13
土
7/
8%
群馬県などの国内産
わけあり
牛乳 KOO
成分散調整
「コープ牛乳」
¥198
参考税込
税込 213円
商品は店頭でご確認ください。
7/13 0
1000ml
178
参考税込
8% 192
子音 "14
子育て14日
ポイント
5 倍デー
co-op
岩手ひと
岩手ひとめぼれ
国館
洗米
ブルガリア ¥1,680円 1,780円
18% 各
Co-op
・塩味つきえ
・塩味つき茶
【各250g
15
参考税达 17
8%
19100-1
写真は
です
トマト (小箱)
桃(2個)
1パック/
山梨県などの国内産 ¥498円
$398
茶美豚
鹿児島県-
岩手県:
群馬県產
北海道產
100g当り とかち
100g当り
参考同认
8537
8%
番号税込 429 円
co-op
5ke
あらびきポーク
スペ
商品に限りがあるため、品切れの場合はご容赦ください。
●写真は全てイメージです
茶美酥
豚バラ
うすぎり
ポイントカードはお会計時にご提示ください
明治
特別栽培米
20 特別栽培無洗米
岩手ひとめぼれ 岩手ひとめぼれ
5kg
5kg
ポイントカードはお会計時にご提示ください プリマハム
総菜コーナー
11時販売開始
(本
彩り手巻き寿司
入り)
4本入
658円
710円
本 198円 本 本 378 円
参考税込
※税込) 213円 (交雑種) 税込
408円
販売開始
7種の天ぷら
盛り合わせ
1バック
398円
Dead 429
·伊右衛門
烏龍茶
各2L
配合 138 円
税込
8%
サントリー
税込 149 円
"15"16
ほほえみ
ポイント
15 モチー
限り
スモークの
香薰
こうくん
金賞受賞
香あらびき
キッコーマン ポーク体 238円
濃いだし ウインナー 参考税込 257円
めんつゆ
本つゆ
1L
大体228円
参考税込
税込 246円
※写真はイメージです
本つゆ
通常の5倍
90g×2
合わせ味噌
麺づくり
7/10 水 16 火 お野菜
いつも
※写真は全てイメージです。
おトク宣言!
群馬県などの
国内産
レタス
店内のこの
群馬県などの
国内産
きゃべつ
meiji
くちど
ヨーグルト
明治
R
ブルガリア
LB81
税込 1,814 円
税込 1,922 円
¥400g
LBSD プレーン
ヨーグルトの正本
全体 138円
見た目のキレイ
見た目のキレイ
LROT
参考税込
WWB 400M
税込 149 円
通常の
Aroma
ネスレ
Rich
25
Aroma
Rich
25
www
エクセラ
倍
・無糖
サイズ
コースの
甘さひかえめ お一家族様よりどり2点限り
【茶美豚
マルちゃん
NESCAFE
Excell
Freally
NESCAFE 各900ml
100g当り
ライオン
鹿児島県・
体各
¥78円
アロマリッチ
円 ジュリエット 合 378円 茶美豚
岩手県・群馬県産
198
参考税込
各 84 円
・キャサリン
豚ロース生姜焼・
参考税込
8% 各4円 各詰替950ml
税込 各 415円 豚丼用
参考税込。
8%
1 213 円
麺づくり
・鶏ガラ醤油
0円 ・合わせ味噌合 118
・鶏だし塩 [参考税込
0円 各1食
日香 127円
1個
108
参考税込 116円
1個
138
円 国内産
1個
お酒酒などの肴 158円
税込 149円 ブロッコリー 170円
8%
商品に限りがあるため、品切れの場合はご容赦ください。
●商品に併記している「参考税込」は、お支払い金額の目安として表示しています。 消費税は、レジで精算する際にお買い物小計に対してかかります。 ●酒類・日用品・雑貨などは消費税率10%対象です。 ●お酒は20歳未満の方への販売は致しておりません。
ざいません。
減にもつながります。
①Aグループ版 ウラ
COOP ユーコース
毎週
土曜日は子育て5倍デー 毎月5日 15日 15日 読み
シニア・
ほほえみ
ポイント
本 5 倍デー 7/100-160
組合員限定プレゼント!
対象商品を1点お買上げにつき
レジにて表示のポイントを
プレゼント致します。
広告の売り出し期間
ポイント
「プレゼント
※写真はイメージです
写真はイメージです。
広告実施店 よくお確かめの上、ご来店ください。
冷L中華
しょうゆだま
0000
冷中華
・ごまだれ
5
ポイント
プレゼント
CCO-OP 冷し中華
本番 218 円
・しょうゆだれ・ごまだれ 参考税込 235円
各110g×3食
「ラーメン
19
10%
「プレゼント」
COOD ざるラーメン 各¥ 298円
和風しょうゆつゆ
110g×3食
●税込 321 円
群馬県などの
国内産
たま
各
7/100 140
表示価格は
7/100 140
co-op
を味わう!
「とっておき
北海道産小麦使用
釜揚げうどん
400g
2番 160円)
● 172 円
10%
表示しています。
※写真はイメージです。
乾麺 10%
10%を表示しています。
コーナーのります。
品がございます。
本 158 円
きゅうり 1袋 170m
高知県などの
国内産
おくら 1ネット
149
●写真はイメージです
・コス
MENU
7/10 160
暴口
co-op & コスモ
直火燒
カレールーカレールー
**
カレールー
[カレール
中華
・中辛・辛口
•直火燒
よりどり
108278 (20
税込
300円
りんごカレー
各8皿分
かつお
メージです
うなぎ
神奈川食
ALCI
8594-2580
中原
230-463-36-30
並木あおば店
23342-758-2141
あさ9時よる9
ACC
末吉店 ハーモス深谷 片
045-581-0850 045-853-1141
洋光台店 神大寺店 竹
045-833-1537 045-431-3630
AC
セレク
04
ジョン 指定
鹿児島:大隅産
うなぎ蒲焼(長焼)
本 2,380円
白根店長後駅前店
045-954-1254
0466-43-4121
AC
南台店 茅ヶ崎高
1尾1バック
●者税込 2,570円
20-466-44-7750
0467-51-8777 46
ガッツリお肉で
スタミナチャージ!
[●写真は
イメージ
[100g当り
378円
税込 408円
税込298円
mmmm321
うまさのためにしない
強いこだわり
●平から収屋
当日出荷
さん兄
5
100g当り
全 498 円
ニュージーランド
ニュージーランドビーフ
牛リブロースステーキ 537円
●写真は
ニュージー
ニュージーランドビーフ
牛モモかたまり
ポイント
プレゼント
[焼そば
co-a
ACC
南林間店 ハーモス 厚木戸店
046-274-7202 046-257-3335 045-295-6600
AC
秦野曽屋店
0463-75-0357 0463-83-2830
ALG
城北店 千代田店 富士中央店
54-247-1326 054-264-1991 25-45-55-2555
新沢田店 袋井田町店 小豆店
-25-5000 239-43-7020 053-473-553
さんじの店 桜づつみ店
1053-441-8787 BUSS-989-99228
あさ9時30分よる9時
安台店
1045-983-1321
あさ10mよる8時
100g当り
268円
289 円
太麺焼そば
450g×2食
西港倉店
0467-32-5422
as 10 239-30
神記
大谷店
046-235-6432
A218 夏の
235円
8310 239
井田三舞店
044-798-8806
ハーモス
045-912-9955
東严塚駅前店
45-426-921
上今泉店
0046-231-7263
トマカ
●チャージ祭
7月・8月は
10. 20. 30.
税込 537 円
体 498円
アメリカ産
ブラントさんの牛肉
牛バラカルビ焼肉用
KA
御殿場高原
あらびきポーク
190g
138円)
CO-OP
いろいろ使える
味菜卵の
たま 178円 長ねぎ 1袋
国内産品
茨城県などの
198円
価 213 円
● 192 円
慮ください。
コース 高知県産
産直 黄金しょうが
+ 100円
総菜コーナー 11時販売開始
●写真はイメージです
バック
みょうが(2本): 138円 良) 138円
*税込108円
愛知県の国内産
大業
100g当り
●前
149円
なまぶし
ご飯(いくら)
1袋
があるため、品切れの場合はご容赦ください。
149円
1本釣り刺身用
日光丸で握った 258円
●
使わず
かつおたたき(解凍) 278円
イメージです
冷し中華
COOP
コーコース
7月24号
土用丑の日
3個入
7/130-140
●写真はイコージです
※写真はイメージです。
本
イパック 478 円
24 16
【ご予約承~ 6月15日(土)~7月15日
7月2日月・2日・2日
焼(長焼)
<130g
2380円
2,570 円
本日より1
2.580
しじみ汁に!
EAGEDO
7318
やきとりセット
(もも&ねぎま・たれ)
●516円
バック
4 498 円
537円
入り
ごちそう握り寿司
バック
1,080 円
1,166円
コープ
純正
ごま油
3008
548円
税込591円
イオシッコ
カ
カスピ海
ヨーグルト
グレ 400g
生乳
税込258円
・まさ 278円
82
沖縄県伊平屋島産
味付けもずく
(EHB-REBAV)
70g×3 1バック
コース
178円 税
192
オレ達のえだ豆
4 298円
組合員さんの声
「ほどよいごたえと、
かみしめるほどあふれてくる
ピリカちゃんさん
321がないです!
めください。
ユーコープはいつでもどなたでも加入して、ご利用いただける組合員のお店です。 ホームページはこちらから ユーコープwww.ucoop.or.jp/service/omise ●店舗により一部が異なる場合がございます。万一売り切れの場合はご容敬ください。一部パッケージの
собр
西部エリア

というようにかなり正確に取得できる
以前OCR関連のライブラリで行ったりchatgptで
チラシの内容を表示しようとした時にはできなかったことができた

ただし、スマホの撮影の場合
チラシ以外のものが入ると
その部分まで文字を認識してしまう

次回はチラシの画像のみで行うことにする

チラシの取得は以前Gmailで特定のメールのみ取得することができたので
Shuhooや特売のメールのみ取得し
リンク先から画像を取得すればできそう

あとは画像と数字の結び付け、もしくは
直接商品と価格を結び付けて取得できればOK

gcloudコマンドでApplication Default Credentials (ADC)の作成

gcloudコマンドでApplication Default Credentials (ADC)の作成

https://cloud.google.com/docs/authentication/provide-credentials-adc?hl=ja#local-dev
にリファレンスがある

Application Default Credentials (ADC) は、アプリケーション環境に基づいて認証情報を自動的に検索するために、認証ライブラリが使用する手法です。認証ライブラリは、これらの認証情報を Cloud クライアント ライブラリと Google API クライアント ライブラリで使用可能にします。ADC を使用すると、Google Cloud サービスと API に対するアプリケーションの認証方法を変更せずに、開発環境または本番環境でコードを実行できます

とのこと

参考サイトにしている
https://nikkie-ftnext.hatenablog.com/entry/ocr-with-google-vision-api-python-first-step
では
ユーザー認証情報で進めました
とあるので

gcloud auth application-default login

を実行する

すると
Google Auth Library が Google アカウントへのアクセスをリクエストが要求されるので
アカウントを選択し
許可する

これで
ライブラリで参照するJSONファイルが作られる

ls ~/.config/gcloud/application_default_credentials.json

でファイルがあるか確認できる

ただし
https://nikkie-ftnext.hatenablog.com/entry/ocr-with-google-vision-api-python-first-step
によれば
Vision APIを最初に叩いたとき「The vision.googleapis.com API requires a quota project, which is not set by default.」が返りました
* 案内に沿ってgcloud auth application-default set-quota-project <選んだプロジェクトID>して解決しています
とあるので

gcloud auth application-default set-quota-project 選んだプロジェクトID

とした

Credentials saved to file: [/Users/snowpool/.config/gcloud/application_default_credentials.json]

These credentials will be used by any library that requests Application Default Credentials (ADC).

Quota project "選んだプロジェクトID" was added to ADC which can be used by Google client libraries for billing and quota. Note that some services may still bill the project owning the resource.

というログが出る

ls ~/.config/gcloud/    

で調べたら

access_tokens.db			default_configs.db
active_config				gce
application_default_credentials.json	legacy_credentials
config_sentinel				logs
configurations				virtenv
credentials.db

となっていた

次に依存ライブラリのインストール

pip install google-cloud-vision

しかし

Collecting google-cloud-vision
  Downloading google_cloud_vision-3.7.3-py2.py3-none-any.whl.metadata (5.2 kB)
Requirement already satisfied: google-api-core!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1 in ./.pyenv/versions/3.10.6/lib/python3.10/site-packages (from google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-cloud-vision) (2.11.0)
Requirement already satisfied: google-auth!=2.24.0,!=2.25.0,<3.0.0dev,>=2.14.1 in ./.pyenv/versions/3.10.6/lib/python3.10/site-packages (from google-cloud-vision) (2.18.0)
Collecting proto-plus<2.0.0dev,>=1.22.3 (from google-cloud-vision)
  Downloading proto_plus-1.24.0-py3-none-any.whl.metadata (2.2 kB)
Requirement already satisfied: protobuf!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0dev,>=3.20.2 in ./.pyenv/versions/3.10.6/lib/python3.10/site-packages (from google-cloud-vision) (3.20.3)
Requirement already satisfied: googleapis-common-protos<2.0dev,>=1.56.2 in ./.pyenv/versions/3.10.6/lib/python3.10/site-packages (from google-api-core!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-cloud-vision) (1.59.0)
Requirement already satisfied: requests<3.0.0dev,>=2.18.0 in ./.pyenv/versions/3.10.6/lib/python3.10/site-packages (from google-api-core!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-cloud-vision) (2.28.2)
Collecting grpcio<2.0dev,>=1.33.2 (from google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-cloud-vision)
  Downloading grpcio-1.65.1-cp310-cp310-macosx_12_0_universal2.whl.metadata (3.3 kB)
Collecting grpcio-status<2.0dev,>=1.33.2 (from google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-cloud-vision)
  Downloading grpcio_status-1.65.1-py3-none-any.whl.metadata (1.1 kB)
Requirement already satisfied: cachetools<6.0,>=2.0.0 in ./.pyenv/versions/3.10.6/lib/python3.10/site-packages (from google-auth!=2.24.0,!=2.25.0,<3.0.0dev,>=2.14.1->google-cloud-vision) (5.3.0)
Requirement already satisfied: pyasn1-modules>=0.2.1 in ./.pyenv/versions/3.10.6/lib/python3.10/site-packages (from google-auth!=2.24.0,!=2.25.0,<3.0.0dev,>=2.14.1->google-cloud-vision) (0.3.0)
Requirement already satisfied: six>=1.9.0 in ./.pyenv/versions/3.10.6/lib/python3.10/site-packages (from google-auth!=2.24.0,!=2.25.0,<3.0.0dev,>=2.14.1->google-cloud-vision) (1.16.0)
Requirement already satisfied: urllib3<2.0 in ./.pyenv/versions/3.10.6/lib/python3.10/site-packages (from google-auth!=2.24.0,!=2.25.0,<3.0.0dev,>=2.14.1->google-cloud-vision) (1.26.14)
Requirement already satisfied: rsa<5,>=3.1.4 in ./.pyenv/versions/3.10.6/lib/python3.10/site-packages (from google-auth!=2.24.0,!=2.25.0,<3.0.0dev,>=2.14.1->google-cloud-vision) (4.9)
INFO: pip is looking at multiple versions of grpcio-status to determine which version is compatible with other requirements. This could take a while.
  Downloading grpcio_status-1.64.1-py3-none-any.whl.metadata (1.1 kB)
  Downloading grpcio_status-1.64.0-py3-none-any.whl.metadata (1.1 kB)
  Downloading grpcio_status-1.63.0-py3-none-any.whl.metadata (1.1 kB)
  Downloading grpcio_status-1.62.2-py3-none-any.whl.metadata (1.3 kB)
Collecting protobuf!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0dev,>=3.20.2 (from google-cloud-vision)
  Downloading protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl.metadata (541 bytes)
Requirement already satisfied: pyasn1<0.6.0,>=0.4.6 in ./.pyenv/versions/3.10.6/lib/python3.10/site-packages (from pyasn1-modules>=0.2.1->google-auth!=2.24.0,!=2.25.0,<3.0.0dev,>=2.14.1->google-cloud-vision) (0.5.0)
Requirement already satisfied: charset-normalizer<4,>=2 in ./.pyenv/versions/3.10.6/lib/python3.10/site-packages (from requests<3.0.0dev,>=2.18.0->google-api-core!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-cloud-vision) (3.0.1)
Requirement already satisfied: idna<4,>=2.5 in ./.pyenv/versions/3.10.6/lib/python3.10/site-packages (from requests<3.0.0dev,>=2.18.0->google-api-core!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-cloud-vision) (3.4)
Requirement already satisfied: certifi>=2017.4.17 in ./.pyenv/versions/3.10.6/lib/python3.10/site-packages (from requests<3.0.0dev,>=2.18.0->google-api-core!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-cloud-vision) (2022.12.7)
Downloading google_cloud_vision-3.7.3-py2.py3-none-any.whl (466 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 466.4/466.4 kB 4.3 MB/s eta 0:00:00
Downloading proto_plus-1.24.0-py3-none-any.whl (50 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 50.1/50.1 kB 2.5 MB/s eta 0:00:00
Downloading grpcio-1.65.1-cp310-cp310-macosx_12_0_universal2.whl (10.4 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 10.4/10.4 MB 8.5 MB/s eta 0:00:00
Downloading grpcio_status-1.62.2-py3-none-any.whl (14 kB)
Downloading protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl (394 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 394.2/394.2 kB 8.9 MB/s eta 0:00:00
Installing collected packages: protobuf, grpcio, proto-plus, grpcio-status, google-cloud-vision
  Attempting uninstall: protobuf
    Found existing installation: protobuf 3.20.3
    Uninstalling protobuf-3.20.3:
      Successfully uninstalled protobuf-3.20.3
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
mediapipe 0.10.9 requires protobuf<4,>=3.11, but you have protobuf 4.25.3 which is incompatible.
Successfully installed google-cloud-vision-3.7.3 grpcio-1.65.1 grpcio-status-1.62.2 proto-plus-1.24.0 protobuf-4.25.3

[notice] A new release of pip is available: 24.0 -> 24.1.2
[notice] To update, run: pip install --upgrade pip

となる

chatgptによれば
インストールは成功したようですが、mediapipeパッケージとprotobufのバージョンに互換性の問題があります。mediapipeはprotobufの3.11から4未満のバージョンを必要としていますが、現在インストールされているprotobufのバージョンは4.25.3です。
とのこと

提示された解決策は
1. protobufのバージョンを互換性のあるバージョンにダウングレードする:
bashコードをコピーする

pip install protobuf==3.20.3
これにより、protobufをmediapipeと互換性のあるバージョンに戻すことができますが、google-cloud-visionと競合する可能性があります。
2. mediapipeの新しいバージョンを探す: mediapipeのドキュメントや問題追跡システムをチェックして、新しいprotobufバージョンと互換性のあるmediapipeのバージョンやワークアラウンドを探します。
3. 仮想環境を使用する: プロジェクトごとに異なるバージョンのパッケージを必要とする場合は、仮想環境を作成することをお勧めします。これにより、パッケージの競合を避けることができます。

とのこと

mediapipeの最新バージョンは?
最新のmediapipeのバージョンは0.10.14です。このバージョンは2024年5月8日にリリースされました。インストールするには、以下のコマンドを使用してください:

pip install mediapipe==0.10.14

とのことなので
これを実行

再度

pip install google-cloud-vision

を実行するとエラーは消えた

次はサンプルコードを動かす

gcloud の初期化

gcloud を初期化

gcloud CLI をインストールする
を参考に続ける

gcloud -v 

を実行すると

Google Cloud SDK 477.0.0
bq 2.1.4
core 2024.05.17
gcloud-crc32c 1.0.0
gsutil 5.29
Updates are available for some Google Cloud CLI components.  To install them,
please run:
  $ gcloud components update

となる

gcloud CLI のコンポーネントの管理
によれば

gcloud components update コマンドを使用して、インストールされているすべてのコンポーネントを、使用可能な最新バージョンの gcloud CLI に更新できる

以前正常に動作していたバージョンに戻す必要があり、gcloud CLI を直接インストール(パッケージ マネージャーではなく、インタラクティブ インストーラ、静的バージョン、Windows インストーラ、Homebrew などを使用して)している場合は、gcloud components update を使用して、指定したバージョンに戻します。

gcloud components update –version VERSION

とあるので
多分失敗しても戻せるはず
ログでバージョンが判明しているので
一度更新してみる

実行すると

To help improve the quality of this product, we collect anonymized usage data 
and anonymized stacktraces when crashes are encountered; additional information 
is available at <https://cloud.google.com/sdk/usage-statistics>. This data is 
handled in accordance with our privacy policy 
<https://cloud.google.com/terms/cloud-privacy-notice>. You may choose to opt in 
this collection now (by choosing 'Y' at the below prompt), or at any time in the
 future by running the following command:

    gcloud config set disable_usage_reporting false

となるが
N
にしておく

次に

Beginning update. This process may take several minutes.


Your current Google Cloud CLI version is: 477.0.0
You will be upgraded to version: 484.0.0

┌───────────────────────────────────────────────────────────────────────────┐
│                     These components will be updated.                     │
├───────────────────────────────────────────────────┬────────────┬──────────┤
│                        Name                       │  Version   │   Size   │
├───────────────────────────────────────────────────┼────────────┼──────────┤
│ BigQuery Command Line Tool                        │      2.1.7 │  1.7 MiB │
│ Cloud Storage Command Line Tool                   │       5.30 │ 11.3 MiB │
│ Google Cloud CLI Core Libraries                   │ 2024.07.12 │ 19.1 MiB │
│ Google Cloud CRC32C Hash Tool (Platform Specific) │      1.0.0 │  1.2 MiB │
│ gcloud cli dependencies                           │ 2024.07.12 │ 16.6 MiB │
└───────────────────────────────────────────────────┴────────────┴──────────┘
┌────────────────────────────────────────────────────────────────────┐
│                These components will be installed.                 │
├─────────────────────────────────────────────┬────────────┬─────────┤
│                     Name                    │  Version   │   Size  │
├─────────────────────────────────────────────┼────────────┼─────────┤
│ gcloud cli dependencies (Platform Specific) │ 2021.04.16 │ < 1 MiB │
└─────────────────────────────────────────────┴────────────┴─────────┘

The following release notes are new in this upgrade.
Please read carefully for information about new features, breaking changes,
and bugs fixed.  The latest full release notes can be viewed at:
  https://cloud.google.com/sdk/release_notes

484.0.0 (2024-07-16)
  Breaking Changes
      ▪ **(GKE Hub)** gcloud container fleet memberships get-credentials now
        requires the permission gkehub.gateway.generateCredentials
        (automatically included in roles gkehub.gatewayReader,
        gkehub.gatewayEditor, and gkehub.gatewayAdmin), as well as network
        access to *connectgateway.googleapis.com.

  AlloyDB
      ▪ Added --node-ids flag to gcloud alloydb instances restart command in
        the alpha and beta tracks. This flag allows users to allow users to
        specify a comma-separated list of read pool node IDs to perform the
        restart on. Without specifying this flag, every node in the read pool
        will be restarted.

  App Engine
      ▪ Removed Google App Engine PHP 5/5 support.

      ▪ Updated the Java SDK to version 2.0.29 build from the open source
        project
        <https://github.com/GoogleCloudPlatform/appengine-java-standard/releases/tag/v2.0.29>.

  Artifact Registry
      ▪ Fixed error codes for gcloud artifacts docker upgrade migrate.

  Batch
      ▪ Fixed the --filter flag of gcloud batch list command to match gcloud
        topic filters syntax.

  BigQuery
      ▪ Added support for non-ASCII characters in the field mask when
        updating Connections.
      ▪ Added support for configuration.authentication.profile_id in the
        field mask when updating Connections.
      ▪ Fixed a bug where bq init would be called even when --use_google_auth
        is specified.

  Cloud Build
      ▪ Add support in gcloud builds worker-pools commands for default region
        set in config.

  Cloud Data Fusion
      ▪ Added three new optional arguments to gcloud beta data-fusion
        instances create command:
        ◆ --maintenance-window-start
        ◆ --maintenance-window-end
        ◆ --maintenance-window-recurrence
        ◆ These arguments allow users to specify the start time, end time,
          and recurrence of the maintenance window for their Data Fusion
          instance.
      ▪ Add four new optional arguments to gcloud beta data-fusion instances
        update command:
        ◆ --maintenance-window-start
        ◆ --maintenance-window-end
        ◆ --maintenance-window-recurrence
        ◆ --clear-maintenance-window
        ◆ These arguments allow users to update maintenance window for their
          Data Fusion instance by specifying the start time, end time, and
          recurrence, or clear the maintenance window using
          --clear-maintenance-window.

  Cloud Run
      ▪ Allows --revision-suffix to be specified with empty string to clear
        client-set revision naming.

  Cloud SQL
      ▪ Added --[no-]enable-dataplex-integration flag to gcloud sql instances
        create and gcloud sql instances patch to support Dataplex Integration
        for Cloud SQL.
      ▪ Added support for MySQL 8.4.

  Cloud Spanner
      ▪ Promoted --type=DATABASE_CHANGE_QUORUM option in gcloud spanner
        operations list to GA.
      ▪ Fixed the DATABASE_CHANGE_QUORUM type filter string in gcloud spanner
        operations list.

  Cloud Workstations
      ▪ Adding disable_ssl_validation support for workstations
        start-tcp-tunnel and workstations ssh.

  Compute Engine
      ▪ Added gcloud compute routers add-route-policy-term which adds policy
        term to a Route Policy in Cloud Router.
      ▪ Promoted gcloud compute routers add-route-policy-term to beta.
      ▪ Added gcloud compute routers update-route-policy-term which updates
        policy term in a Route Policy in Cloud Router.
      ▪ Promoted gcloud compute routers update-route-policy-term to beta.
      ▪ Added gcloud compute routers remove-route-policy-term which removes
        policy term from Route Policy in Cloud Router.
      ▪ Promoted gcloud compute routers remove-route-policy-term to beta.
      ▪ Fixed a bug in gcloud beta compute ssh where a third-party identity
        subject bearing an '@' sign wouldn't be URL-escaped in the way the OS
        Login API expects, causing spurious rejection.
      ▪ Promoted support of flags to --detection-load-threshold,
        detection-absolute-qps, detection-relative-to-baseline-qps, and
        traffic-granularity-configs in gcloud compute security-policies
        add-layer7-ddos-defense-threshold-config to GA.

  Dataproc Metastore
      ▪ Promoted --min-scaling-factor, --max-scaling-factor, and
        --autoscaling-enabled flag of gcloud metastore services create and
        gcloud metastore services update to GA.

  Distributed Cloud Edge
      ▪ Added --offline-reboot-ttl flag to gcloud edge-cloud container
        clusters create and gcloud edge-cloud container clusters update
        commands. This flag specifies the maximum duration a node can reboot
        offline (without connection to Google) and then rejoin its cluster to
        resume its designated workloads.

  Kubernetes Engine
      ▪ Added flag option --addons=RayOperator to enable/disable the Ray
        Operator addon for GKE Standard clusters.
      ▪ Added flag --[no]-enable-ray-operator to enable/disable the Ray
        Operator addon for GKE Autopilot clusters.
      ▪ Added flag --[no]-enable-ray-cluster-logging to enable/disable
        automatic log collection for Ray clusters when the Ray Operator addon
        is enabled.
      ▪ Added flag --[no]-enable-ray-cluster-monitoring to enable/disable
        automatic metrics collection for Ray clusters when the Ray Operator
        addon is enabled.

    Subscribe to these release notes at
    https://groups.google.com/forum/#!forum/google-cloud-sdk-announce
    (https://groups.google.com/forum/#!forum/google-cloud-sdk-announce).

483.0.0 (2024-07-02)
  Google Cloud CLI
      ▪ Enabled faster component update mode by default on Linux. This avoids
        making a backup copy of the installation directory when running certain
        gcloud components commands, which should significantly improve the time
        taken by these operations (including installation and updates).
      ▪ Fixed issue where gcloud components update would leave installation
        in an unusable state when downloading certain components failed.

  AlloyDB
      ▪ Added the following flags to gcloud alloydb instances create and
        gcloud alloydb instances update in alpha and beta:
        ◆ --observability-config-enabled
        ◆ --observability-config-preserve-comments
        ◆ --observability-config-track-wait-events
        ◆ --observability-config-max-query-string-length
        ◆ --observability-config-record-application-tags
        ◆ --observability-config-query-plans-per-minute
        ◆ --observability-config-track-active-queries
      ▪ Promoted AlloyDB Cross Region Replication commands to beta and GA
        track. Modified commands include: alloydb clusters switchover.
      ▪ Added creating cross region and project backups support to gcloud
        alloydb backups create command.
      ▪ Added ability to create clusters with database_version POSTGRES_16 in
        beta track.

  Batch
      ▪ Release resource-allowances commands to the alpha track.

  Cloud Access Context Manager
      ▪ Promoted gcloud access-context-manager supported-services to GA.

  Cloud Filestore
      ▪ Enable Filestore promote-replica command in GA track.

  Cloud Functions
      ▪ Added --binary-authorization and --clear-binary-authorization flags
        for 2nd gen function in alpha and beta track.

  Cloud NetApp
      ▪ Updated psa-range comments on gcloud netapp storage-pools and gcloud
        netapp volumes to indicate that the psa-range key is not used and will
        be ignored.

  Cloud SQL
      ▪ Adding support for clean and if-exists flags to parallel import and
        single-threaded-export.

  Cloud Workstations
      ▪ Added --vm-tags flag to gcloud workstations config create to add tags
        to the workstation's underlying VM.

  Compute Engine
      ▪ Promoted --preference flag of gcloud compute backend-services
        add-backend and gcloud compute backend-services update-backend to GA.
      ▪ Promoted --service-lb-policy flag of gcloud compute backend-services
        create and gcloud compute backend-services update to GA.
      ▪ Promote gcloud compute instances ops-agents to GA.
      ▪ Added IDPF to the list of guestOsFeatures.
      ▪ Promoted --max-run-duration flag of gcloud compute instances create
        to v1.
        ◆ Allows specifying the duration of time after which the instance
          will terminate.
      ▪ Promoted --termination-time flag of gcloud compute instances create
        to v1.
        ◆ Allows specifying the timestamp that the instance will terminate.
      ▪ Promoted --discard-local-ssds-at-termination-timestamp flag of gcloud
        compute instances create to v1.
        ◆ Allows specifying the option to whether discard attached local SSDs
          when automatically stopping this VM

  Network Security
      ▪ Renamed FIREWALL_POLICY column to SOURCE_RESOURCE column in gcloud
        networksecurity address-groups list-references command.
      ▪ Added --purpose flag to gcloud alpha/beta network-security
        address-groups create/update commands.

  Secret Manager
      ▪ Added flag --location and --regional-kms-key-name for secrets to use
        the regional secrets.

    Subscribe to these release notes at
    https://groups.google.com/forum/#!forum/google-cloud-sdk-announce
    (https://groups.google.com/forum/#!forum/google-cloud-sdk-announce).

482.0.0 (2024-06-25)
  App Engine
      ▪ Removed unused python2 dependencies that have CVEs.

  Cloud Bigtable
      ▪ Adds force option to cbt setgcpolicy.

  Cloud Dataflow
      ▪ Elevate jinja variables to top-level flag in dataflow yaml run.

  Cloud Functions
      ▪ Added --clear-build-service-account flag for gcloud functions deploy.

  Cloud Key Management Service
      ▪ Added --allowed-access-reasons flag to gcloud kms keys create to
        create a key with a Key Access Justifications policy configured.
      ▪ Added --allowed-access-reasons flag to gcloud kms keys update to
        update the Key Access Justifications policy on a key.
      ▪ Added --remove-key-access-justifications-policy flag to gcloud kms
        keys update to remove the Key Access Justifications policy on a key.

  Cloud Services
      ▪ Promoted gcloud services policies add-enable-rules to beta.
      ▪ Promoted gcloud services policies remove-enable-rules to beta.
      ▪ Promoted gcloud services policies get to beta.
      ▪ Promoted gcloud services policies get-effective to beta.
      ▪ Promoted gcloud services policies test-enabled to beta.
      ▪ Promoted gcloud services groups list-ancestor-groups to beta.
      ▪ Promoted gcloud services groups list-descendant-services to beta.
      ▪ Promoted gcloud services groups list-members to beta.

  Compute Engine
      ▪ Added --size flag to gcloud compute instance-groups managed update
        for v1.
      ▪ Promoted --confidential-compute-type flag for the command gcloud
        compute instance create to GA.
      ▪ Promoted --performance-monitoring-unit flag for the command gcloud
        compute instance-templates create to GA.
      ▪ Promoted --performance-monitoring-unit flag for the command gcloud
        compute instances bulk create to GA.
      ▪ Promoted --performance-monitoring-unit flag for the command gcloud
        compute instances create  to GA.

  Kubernetes Engine
      ▪ Updated default kubectl from 1.27.14 to 1.27.15.
      ▪ Additional kubectl versions:
        ◆ kubectl.1.27 (1.27.15)
        ◆ kubectl.1.28 (1.28.11)
        ◆ kubectl.1.25 (1.29.6)
        ◆ kubectl.1.30 (1.30.2)

  Network Connectivity
      ▪ Added include-import-ranges flag to hybrid spoke creation to support
        importing hub subnets.

    Subscribe to these release notes at
    https://groups.google.com/forum/#!forum/google-cloud-sdk-announce
    (https://groups.google.com/forum/#!forum/google-cloud-sdk-announce).

481.0.0 (2024-06-18)
  Breaking Changes
      ▪ **(Cloud Dataflow)** Deprecated gcloud dataflow sql command group.
        The command group will be removed by 2025-01-31. See Beam YAML
        (https://beam.apache.org/documentation/sdks/yaml/) and Beam notebooks
        (https://cloud.google.com/dataflow/docs/guides/notebook-advanced#beam-sql)
        for alternatives.

  AlloyDB
      ▪ Added another option ASSIGN_IPV4 to flag --assign-inbound-public-ip
        to enable public IP for an instance to gcloud alloydb instances create
        and gcloud alloydb instances create-secondary.
      ▪ Added flag --authorized-external-networks to set a list of authorized
        external networks on an instance to gcloud alloydb instances create and
        gcloud alloydb instances create-secondary.
      ▪ Added switchover command.

  Artifact Registry
      ▪ Fixed a bug where gcloud artifacts files download and gcloud
        artifacts generic download would crash.

  BigQuery
      ▪ Added undelete command for datasets.
      ▪ Updated google-auth to version 2.29.0.
      ▪ Improved authentication error messaging.

  Cloud Domains
      ▪ Implemented the following commands for gcloud domains registrations
        google-domains-dns
        ◆ get-forwarding-config
        ◆ export-dns-record-sets

  Cloud Filestore
      ▪ Added --source-instance flag to gcloud filestore instances create and
        gcloud beta filestore instances create command to specify the instance
        will be created as a Standby replica of the source-instance.
      ▪ Added promote-replica verb for filestore instances. promote-replica
        promotes a standby replication instance to a regular instance.

  Cloud Functions
      ▪ Promoted --build-service-account flag for gcloud functions deploy to
        GA.

  Cloud Identity-Aware Proxy
      ▪ Promoted gcloud iap regional command to beta and GA.

  Cloud Pub/Sub
      ▪ Promoted --cloud-storage-use-topic-schema flag of gcloud pubsub
        subscriptions create to GA. Added the ability to set whether to use
        topic schemas in Cloud Pub/Sub to Cloud Storage subscriptions. For more
        information, see
        <https://cloud.google.com/pubsub/docs/create-cloudstorage-subscription#use-topic-schema>.
      ▪ Promoted --cloud-storage-use-topic-schema flag of gcloud pubsub
        subscriptions update. to GA. Added the ability to update whether to use
        topic schemas in Cloud Pub/Sub to Cloud Storage subscriptions. For more
        information, see
        <https://cloud.google.com/pubsub/docs/create-cloudstorage-subscription#use-topic-schema>.

  Cloud Spanner
      ▪ Added gcloud beta spanner instance-partitions command group.
      ▪ Added --instance-partition flag to gcloud beta spanner operations
        list, gcloud beta spanner operations describe, and gcloud beta spanner
        operations cancel.

  Cloud Storage
      ▪ Added commands for creating, listing, describing, and deleting
        folders in buckets with hierarchical namespace enabled:
        ◆ Added gcloud alpha storage folders create which creates folders.
        ◆ Added gcloud alpha storage folders list which lists folders in
          buckets.
        ◆ Added gcloud alpha storage folders describe which gets the folder's
          metadata.
        ◆ Added gcloud alpha storage folders delete which deletes folders.
      ▪ Updated gsutil component to 5.30.

  Compute Engine
      ▪ Promoted --confidential-compute-type flag for the command gcloud
        compute instance create to GA.
      ▪ Added --size flag to gcloud compute instance-groups managed update
        for v1.

  Network Connectivity
      ▪ Updated gcloud network-connectivity internal-ranges update to support
        setting and clearing labels.
      ▪ Added support for include-export-ranges to support include filters
        for VPC spokes.

    Subscribe to these release notes at
    https://groups.google.com/forum/#!forum/google-cloud-sdk-announce
    (https://groups.google.com/forum/#!forum/google-cloud-sdk-announce).

480.0.0 (2024-06-11)
  App Engine
      ▪ Updated the Java SDK to version 2.0.28 build from the open source
        project
        <https://github.com/GoogleCloudPlatform/appengine-java-standard/releases/tag/v2.0.28>.

  Artifact Registry
      ▪ gcloud artifacts docker upgrade migrate now automatically creates
        repos for pkg.dev-based migration.
        ◆ Added gcloud artifacts files delete command.

  Cloud Datastream
      ▪ Added --type and --sqlserver-* flags to gcloud datastream
        connection-profiles create|update and gcloud datastream objects lookup
        commands to support SQL server source.
      ▪ Added --type and --sqlserver-* flags to gcloud datastream streams
        create|update commands to support SQL server source.
      ▪ Added --sqlserver-rdbms-file flag and support for SQL Server profile
        to --connection-profile-object-file to gcloud datastream
        connection-profiles discover commands to support SQL server source.

  Cloud Domains
      ▪ Implemented the following commands for gcloud domains registrations
        ◆ renew-domain
        ◆ initiate-push-transfer

  Cloud Functions
      ▪ Added support for --execution-id flag when used together with --gen2
        flag for gcloud functions logs read.

  Cloud Healthcare
      ▪ Added beta flag --enable-history-modifications to the fhir-stores
        create and fhir-stores update commands.

  Cloud IAM
      ▪ Updated iam service-accounts keys list to return additional
        properties, namely:
        ◆ disable_reason: The reason the Service Account Key as been disabled
          (if applicable)
        ◆ extended_status: Additional metadata about the Service Account Key

  Cloud Memorystore
      ▪ Added --zone-distribution-mode and --zone flags to gcloud redis
        clusters create for creating single zone clusters.

  Cloud Pub/Sub
      ▪ Added --bigquery-service-account-email and
        --cloud-storage-service-account-email flags to gcloud pubsub
        subscriptions create to set the service account for writing messages to
        BigQuery and Cloud Storage, respectively.
      ▪ Added --bigquery-service-account-email and
        --cloud-storage-service-account-email flags to gcloud pubsub
        subscriptions create to update the service account for writing messages
        to BigQuery and Cloud Storage, respectively.

  Cloud Spanner
      ▪ Added --proto-descriptors-file to gcloud spanner databases create
        command to allow creating database with proto and enum type columns.
      ▪ Added --proto-descriptors-file to gcloud spanner databases ddl update
        command to allow updating database with proto and enum type columns.
      ▪ Added --include-proto-descriptors to gcloud spanner databases ddl
        describe command to allow proto descriptors for a database with proto
        and enum type columns.
      ▪ Promoted gcloud spanner databases change-quorum command to GA.

  Cloud Storage
      ▪ Adds support of Cross Bucket Replication Feature in alpha track of
        gcloud transfer command group.

  Cloud Workstations
      ▪ Added --allowed-ports flag to gcloud beta workstations configs create
        and gcloud beta workstations configs update commands.
      ▪ Added enable-nested-virtualization pool-size and boot-disk-size to
        --boost-configs flag in beta workstations configs create and beta
        workstations configs update.

  Compute Engine
      ▪ Added support for version=24.04 and short-name=ubuntu in --os-types
        for gcloud beta compute instances ops-agents policies [create|update].
      ▪ Promoted Tls Early Data in TargetHttpsProxy compute API to v1.
      ▪ Added gce_vm_ip_portmap Network Endpoint Group for gcloud compute
        network-endpoint-groups beta support.
      ▪ Added --access-mode flag to gcloud compute disks create and gcloud
        compute disks update.
      ▪ Added --tls-early-data flag to gcloud compute v1 target-https-proxies
        create/update to Tls Early Data field in Target Https Proxy.

  Secret Manager
      ▪ Added --version-destroy-ttl flag to gcloud secrets create to let
        users enable secret version delayed destruction on a secret.
      ▪ Added --version-destroy-ttl flag to gcloud secrets update to let
        users enable/update secret version delayed destruction on a secret.
      ▪ Added --remove-version-destroy-ttl flag to gcloud secrets update to
        let users disable secret version delayed destruction on a secret.

    Subscribe to these release notes at
    https://groups.google.com/forum/#!forum/google-cloud-sdk-announce
    (https://groups.google.com/forum/#!forum/google-cloud-sdk-announce).

479.0.0 (2024-06-04)
  Breaking Changes
      ▪ **(Cloud Dataflow)** gcloud dataflow flex-template build for Dataflow
        Flex Templates in Python with --env
        FLEX_TEMPLATE_PYTHON_REQUIREMENTS_FILE=/path/to/requirements.txt
        defined will run pip check after pip install while building the
        container image. This will break the build process if newly installed
        packages override pre-installed packages with a version that is known
        to be incompatible with other pre-installed packages. See
        <https://cloud.google.com/dataflow/docs/guides/templates/configuring-flex-templates>
        for alternative methods to build a container image without pip check.

  Artifact Registry
      ▪ Updated gcloud artifacts docker images command to include tags as
        list instead of string to enable use of --filter=tags=<SearchTerm>.

  Cloud Composer
      ▪ Added gcloud composer environments check-upgrade command. It checks
        that an environment upgrade does not fail because of PyPI module
        conflicts.
      ▪ Added gcloud composer environments list-upgrades command. It lists
        all possible target versions that an existing environment can be
        upgraded to.

  Cloud Dataproc
      ▪ Updated gcloud dataproc session-templates export to filter out
        additional output only fields.

  Cloud NetApp
      ▪ Added --administrators flag to gcloud netapp active-directories
        create and gcloud netapp active-directories update.

  Cloud SQL
      ▪ Added --preferred-secondary-zone flag to gcloud sql instances clone
        command.

  Compute Engine
      ▪ Updated import and export schemas for gcloud compute
        forwarding-rules.
      ▪ Promoted --ip-collection flag of gcloud compute forwarding-rules
        create to GA.
      ▪ Promoted --ip-collection-region flag of gcloud compute
        forwarding-rules create to GA.

  Compute OS Config
      ▪ Added --allow-missing flag to gcloud compute os-config
        os-policy-assignments update to allow for creation of a new OS policy
        assignment resource if it does not exist.

  Database Migration
      ▪ Updated gcloud database-migration connection-profiles create cloudsql
        to support POSTGRES_16 version option for Cloud SQL connection
        profiles.

  Distributed Cloud Edge
      ▪ Added add/remove exclusion window flags for gcloud edge-cloud
        container clusters update to allow users to add/remove exclusion
        windows where automatic upgrades will be blocked within.

  Service Extensions
      ▪ Added the metadata field to the DEP extensions.

    Subscribe to these release notes at
    https://groups.google.com/forum/#!forum/google-cloud-sdk-announce
    (https://groups.google.com/forum/#!forum/google-cloud-sdk-announce).

478.0.0 (2024-05-29)
  Google Cloud CLI
      ▪ Improved error message for authentication errors.
      ▪ Improved error message for service account impersonation refresh
        errors.
      ▪ Fixed issue where some commands with a --uri flag would produce no
        output.

  App Engine
      ▪ Enable fetch_instance_after_connect_error for compute
        start-iap-tunnel in GA.
      ▪ Allow IAP tunneling for instances with external IP when explicitly
        enabled via flag.

  App Engine Flexible Environment
      ▪ Enable fetch_instance_after_connect_error for compute
        start-iap-tunnel in GA.
      ▪ Allow IAP tunneling for instances with external IP when explicitly
        enabled via flag.

  Artifact Registry
      ▪ Added gcloud artifacts files describe command.

  Backup For GKE
      ▪ Added --volume-data-restore-policy-bindings flag to gcloud container
        backup-restore restore-plans create and gcloud container backup-restore
        restore-plans update to enhance volume restore flexibility.
      ▪ Added --volume-data-restore-policy-overrides-file flag to gcloud
        container backup-restore restores create to enhance volume restore
        flexibility.
      ▪ Added --permissive-mode flag to gcloud container backup-restore
        backup-plans create and gcloud container backup-restore backup-plans
        update to enable bypassing the new backup-time restorability
        enforcement.
      ▪ Added --filter-file flag to gcloud container backup-restore restores
        create to support Backup for GKE fine-grained restore.
      ▪ Added --restore-order-file flag to gcloud <alpha|beta> container
        backup-restore restore-plans create and gcloud <alpha|beta> container
        backup-restore restore-plans update to support custom ordering while
        performing restore as part of Backup for GKE.
      ▪ Added the following enum values for the flag
        --namespaced-resource-restore-mode to gcloud <alpha|beta> container
        backup-restore restore-plans create and gcloud <alpha|beta> container
        backup-restore restore-plans update to expand namespaced resource
        restore mode options:
        ◆ merge-skip-on-conflict
        ◆ merge-replace-volume-on-conflict
        ◆ merge-replace-on-conflict
      ▪ Deprecated --substitution-rules-file flag. Use
        --transformation-rules-file instead.

  BigQuery
      ▪ Added support for map_target_type with external parquet tables.
      ▪ Added support for column_name_character_map to map special characters
        in column names during load jobs.
      ▪ Added a printout of unreachable locations when datasets and jobs are
        listed and a region is down.

  Cloud Dataplex
      ▪ Promoted gcloud dataplex aspect-types command group to GA.
      ▪ Promoted gcloud dataplex entry-groups command group to GA.
      ▪ Promoted gcloud dataplex entry-types command group to GA.

  Cloud Deploy
      ▪ Fixed issue where skaffold files generated from deploy releases
        create flags did not include all profiles in the release's Delivery
        Pipeline.

  Cloud Firestore
      ▪ Promoted Cloud Firestore Backups and Restore gcloud CLI changes to
        beta.
        ◆ Promoted gcloud firestore backups list command to beta.
        ◆ Promoted gcloud firestore backups describe command to beta.
        ◆ Promoted gcloud firestore backups delete command to beta.
        ◆ Promoted gcloud firestore backups schedules create command to beta.
        ◆ Promoted gcloud firestore backups schedules update command to beta.
        ◆ Promoted gcloud firestore backups schedules describe command to
          beta.
        ◆ Promoted gcloud firestore backups schedules delete command to beta.
        ◆ Promoted gcloud firestore backups schedules list command to beta.
        ◆ Promoted gcloud firestore databases restore command to beta.
      ▪ Promoted Cloud Firestore Backups and Restore gcloud CLI changes to
        GA.
        ◆ Promoted gcloud firestore backups list command to GA.
        ◆ Promoted gcloud firestore backups describe command to GA.
        ◆ Promoted gcloud firestore backups delete command to GA.
        ◆ Promoted gcloud firestore backups schedules create command to GA.
        ◆ Promoted gcloud firestore backups schedules update command to GA.
        ◆ Promoted gcloud firestore backups schedules describe command to GA.
        ◆ Promoted gcloud firestore backups schedules delete command to GA.
        ◆ Promoted gcloud firestore backups schedules list command to GA.
        ◆ Promoted gcloud firestore databases restore command to GA.

  Cloud Firestore Emulator
      ▪ Release Cloud Firestore emulator v1.19.7
        ◆ Fixes unexpected responses from nested queries in Datastore Mode.
        ◆ Add Auth Context support for Firestore triggers (2nd gen) in
          Firestore Emulator

  Cloud Functions
      ▪ Added validation to --runtime-update-policy argument.

  Cloud SQL
      ▪ Added PostgreSQL 16 to database versions.
      ▪ Fixed issue where gcloud sql instances export and gcloud sql
        instances import would display only the operation selfLink field
        instead of the whole operation when run asynchronously with --async,
        regardless of the --format flag specified.
        ◆ This behavior is now consistent with other gcloud sql instances
          commands.
        ◆ To display only the selfLink field, use --format="value(selfLink)".

  Cloud Workstations
      ▪ Adding --env flag to gcloud workstations create.

  Compute Engine
      ▪ Added IPV6_ONLY option to --stack-type flag of gcloud compute
        vpn-gateways create command to create an IPv6-only VPN gateway.

  Config Connector
      ▪ Updated Google Cloud Config Connector to version 1.118.1. See Config
        Connector Overview for more details
        https://cloud.google.com/config-connector/docs/overview
        (https://cloud.google.com/config-connector/docs/overview).

  Database Migration
      ▪ Updated gcloud database-migrate connection-profiles update to update
        Database Migration Service connection profile for SQL Server to Cloud
        SQL-SQL Server migrations.
      ▪ Updated gcloud database-migrate migration-jobs update to update
        Database Migration Service migration job for SQL Server to Cloud
        SQL-SQL Server migrations.

  Dataproc Metastore
      ▪ Added --deletion-protection flags to gcloud metastore services create
        GA release track to allow creating a Dataproc Metastore instance with
        delete protection.
      ▪ Added --deletion-protection and --no-deletion-protection flags to
        gcloud metastore services update GA release track to allow updating a
        Dataproc Metastore instance with delete protection.

  Security Command Center
      ▪ Added --filter-modules flag in gcloud scc manage services describe
        ... api to filter response by modules.

    Subscribe to these release notes at
    https://groups.google.com/forum/#!forum/google-cloud-sdk-announce
    (https://groups.google.com/forum/#!forum/google-cloud-sdk-announce).

Once started, canceling this operation may leave your SDK installation in an 
inconsistent state.

となる
これで
Y
とすると更新される

Performing in place update...

╔════════════════════════════════════════════════════════════╗
╠═ Uninstalling: BigQuery Command Line Tool                 ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Uninstalling: Cloud Storage Command Line Tool            ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Uninstalling: Google Cloud CLI Core Libraries            ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Uninstalling: Google Cloud CRC32C Hash Tool              ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Uninstalling: gcloud cli dependencies                    ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Installing: BigQuery Command Line Tool                   ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Installing: Cloud Storage Command Line Tool              ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Installing: Google Cloud CLI Core Libraries              ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Installing: Google Cloud CRC32C Hash Tool (Platform S... ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Installing: gcloud cli dependencies                      ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Installing: gcloud cli dependencies (Platform Specific)  ═╣
╚════════════════════════════════════════════════════════════╝

Performing post processing steps...done.                                       

Update done!

To revert your CLI to the previously installed version, you may run:
  $ gcloud components update --version 477.0.0

となるのでログを翻訳

後処理ステップを実行しています…完了しました。

アップデート完了!

CLI を以前にインストールしたバージョンに戻すには、次のコマンドを実行します。
$ gcloud コンポーネントの更新 –バージョン 477.0.0
となる

つまりこのコマンドを実行すれば不具合があっても戻せるはず

とりあえず更新処理はできたので初期化をする

./google-cloud-sdk/bin/gcloud init

を実行

Welcome! This command will take you through the configuration of gcloud.

Your current configuration has been set to: [default]

You can skip diagnostics next time by using the following flag:
  gcloud init --skip-diagnostics

Network diagnostic detects and fixes local network connection issues.
Checking network connection...done.                                            
Reachability Check passed.
Network diagnostic passed (1/1 checks passed).

You must log in to continue. Would you like to log in (Y/n)?  

となるので
Y
にする

これでブラウザで認証画面になるので
ログインして処理を進めていき
最後に許可を押せばOK

Your browser has been opened to visit:


Please enter numeric choice or text value (must exactly match list item):     

となるので
今回使うのプロジェクトの番号を入力

これで

* Commands that require authentication will use snowpoollovely@gmail.com by default
* Commands will reference project `raspberrypi-ea1b6` by default
Run `gcloud help config` to learn how to change individual settings

This gcloud configuration is called [default]. You can create additional configurations if you work with multiple accounts and/or projects.
Run `gcloud topic configurations` to learn more.

Some things to try next:

* Run `gcloud --help` to see the Cloud Platform services you can interact with. And run `gcloud help COMMAND` to get help on any gcloud command.
* Run `gcloud topic --help` to learn about advanced features of the SDK like arg files and output formatting
* Run `gcloud cheat-sheet` to see a roster of go-to `gcloud` commands.

となる

gcloud config list

を実行すると
設定の確認ができる

とりあえず設定はできたので
次に
gcloudコマンドでApplication Default Credentials (ADC)の作成

Google Cloud Vision API の登録

Google Cloud Vision API の登録

https://cloud.google.com/vision/?hl=ja&_gl=1*1yrkeuh*_ga*NzQ0NTYyMjM5LjE2ODQxODU5MzA.*_ga_WH2QY8WWF5*MTcyMTE1MzQ3OS4yLjEuMTcyMTE1MzYyNS42LjAuMA..
でチュートリアル

料金については
https://cloud.google.com/vision/pricing?hl=ja#prices
を参考に
基本的に無料枠でできそう

プロジェクトを選択するのだが
Gmailと同じプロジェクトを選択する

Credentials.json
の中身を見ればOK

とりあえずデフォルトがこれなので
そのまま進める

APIとサービスを有効にする
をクリックし
cloud vision api
で検索

これでAPIを有効にする

多分認証のJSONファイルなので
権限などを増やしても変わらないはず

もしダメなら再度作成するだけ

とりあえずこれで進めてみる

Google colabでも実験できるのだが
Google drive へアップするときに
アップロード先のディレクトリがpublicに共有されていないことを確認すること
不安なら都度アップロードすればOK

とりあえずローカルで動かすのだが
Google Cloud SDK
が必要と chatgpt では言っている

本当か調べてみる

https://nikkie-ftnext.hatenablog.com/entry/ocr-with-google-vision-api-python-first-step
2024-01-03
GoogleのVision APIをPythonから呼び出して、画像内のテキストを検出する
に載っていた

サンプルコードを動かす前に準備が必要です。
「Google Cloud プロジェクトと認証のセットアップ」
* 大前提:Google Cloudのアカウント
* Google Cloudのプロジェクト1つ
* すでにあるものを選ぶ
* または、新規作成
* 余談:削除など管理したい場合は https://console.cloud.google.com/cloud-resource-manager から
* プロジェクトで課金が有効になっているか確認する
* 案内された別ドキュメントに従いました
* 直リンクは https://console.cloud.google.com/billing/linkedaccount?hl=ja&project=<選んだプロジェクトID> っぽいです
* 課金を有効にしますが、今回のサンプルコードの範囲内では無料で使える認識です
* 最初の 1,000 ユニット/月は無料

まではOK

次に
gcloudコマンドが使えるようにする設定が必要

https://cloud.google.com/docs/authentication/provide-credentials-adc?hl=ja#local-dev
の中の
gcloud CLI をインストールして初期化します。
をクリック

gcloud CLI をインストールする
https://cloud.google.com/sdk/docs/install?hl=ja
の中で
各種OSごとの
Google Cloud CLI 
のパッケージがダウンロードできるので
ここからダウンロード

私の場合 Macだけど
M1MacBookAir なので
macOS 64 ビット
(ARM64, Apple M1 silicon)
の方を選ぶ

google-cloud-cli-477.0.0-darwin-arm.tar.gz

をダウンロードしたら
展開して
ホームディレクトリに移動させる

Macの場合
圧縮ファイルをダブルクリックで展開できるので

 mv ~/Downloads/google-cloud-sdk .

でホームディレクトリ直下に移動

./google-cloud-sdk/install.sh

を実行したらエラーになるので

Reason: tried: '/opt/homebrew/opt/openssl@1.1/lib/libssl.1.1.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/opt/openssl@1.1/lib/libssl.1.1.dylib' (no such file), '/opt/homebrew/opt/openssl@1.1/lib/libssl.1.1.dylib' (no such file), '/usr/local/lib/libssl.1.1.dylib' (no such file), '/usr/lib/libssl.1.1.dylib' (no such file, not in dyld cache)

で検索

Library not loaded: libssl.1.1.dylib (LoadError) 発生時の解決方法
によれば
OpenSSL@1.1のインストール
でOK

 brew install openssl@1.1

でインストールできるらしい

既にサポート終了しているはずと思い検索
「OpenSSL」にアップデート – 「同1.1.1」はサポート終了
https://www.security-next.com/149614

最初にchatgptでエラーの解決を調べた時にこの答えが出たけど
以前 YouTube live を再生するコードの時に
昔のライブラリ情報のインストールを提示され
ドツボにハマったことがあったので
念の為検索した

もうちょっと調べたら

PythonがOpenSSL周りのエラーで動かない

2024年05月24日
でこっちも同じ感じ

ただ

brew install openssl@1.1

を実行しても

brew install openssl@1.1

==> Auto-updating Homebrew...
Adjust how often this is run with HOMEBREW_AUTO_UPDATE_SECS or disable with
HOMEBREW_NO_AUTO_UPDATE. Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and homebrew/cask).
==> New Formulae
libgit2@1.7                              tdb
==> New Casks
avbeam                     jagex                      twingate
duplicateaudiofinder       sq-mixpad

You have 23 outdated formulae installed.

Error: Cannot install under Rosetta 2 in ARM default prefix (/opt/homebrew)!
To rerun under ARM use:
    arch -arm64 brew install ...
To install under x86_64, install Homebrew into /usr/local.

となるので

arch -arm64 brew install openssl@1.1

を実行

Warning: openssl@1.1 has been deprecated because it is not supported upstream!
==> Downloading https://ghcr.io/v2/homebrew/core/openssl/1.1/manifests/1.1.1w
######################################################################### 100.0%
==> Fetching openssl@1.1
==> Downloading https://ghcr.io/v2/homebrew/core/openssl/1.1/blobs/sha256:38619f
######################################################################### 100.0%
==> Pouring openssl@1.1--1.1.1w.arm64_sonoma.bottle.tar.gz
==> Caveats
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
  /opt/homebrew/etc/openssl@1.1/certs

and run
  /opt/homebrew/opt/openssl@1.1/bin/c_rehash

openssl@1.1 is keg-only, which means it was not symlinked into /opt/homebrew,
because this is an alternate version of another formula.

If you need to have openssl@1.1 first in your PATH, run:
  echo 'export PATH="/opt/homebrew/opt/openssl@1.1/bin:$PATH"' >> ~/.zshrc

For compilers to find openssl@1.1 you may need to set:
  export LDFLAGS="-L/opt/homebrew/opt/openssl@1.1/lib"
  export CPPFLAGS="-I/opt/homebrew/opt/openssl@1.1/include"

For pkg-config to find openssl@1.1 you may need to set:
  export PKG_CONFIG_PATH="/opt/homebrew/opt/openssl@1.1/lib/pkgconfig"
==> Summary
🍺  /opt/homebrew/Cellar/openssl@1.1/1.1.1w: 8,102 files, 18MB
==> Running `brew cleanup openssl@1.1`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).

最後のメッセージが気になるので翻訳

openssl@1.1 は Keg 専用です。つまり、/opt/homebrew にシンボリックリンクされていません。
これは別の公式の代替バージョンであるためです。

PATH の最初に openssl@1.1 を含める必要がある場合は、次を実行します。
echo ‘export PATH=”/opt/homebrew/opt/openssl@1.1/bin:$PATH”‘ >> ~/.zshrc

コンパイラが openssl@1.1 を見つけるには、次の設定が必要になる場合があります。
エクスポート LDFLAGS=”-L/opt/homebrew/opt/openssl@1.1/lib”
エクスポート CPPFLAGS=”-I/opt/homebrew/opt/openssl@1.1/include”

pkg-config が openssl@1.1 を見つけるには、次の設定が必要になる場合があります。
import PKG_CONFIG_PATH=”/opt/homebrew/opt/openssl@1.1/lib/pkgconfig”
==> まとめ
🍺 /opt/homebrew/Cellar/openssl@1.1/1.1.1w: 8,102 ファイル、18MB
==> `brew cleanup openssl@1.1` を実行しています…
HOMEBREW_NO_INSTALL_CLEANUP を設定して、この動作を無効にします。
これらのヒントは HOMEBREW_NO_ENV_HINTS で非表示にします (「man brew」を参照)。

このため

export LDFLAGS="-L/opt/homebrew/opt/openssl@1.1/lib"
export CPPFLAGS="-I/opt/homebrew/opt/openssl@1.1/include"
export PKG_CONFIG_PATH="/opt/homebrew/opt/openssl@1.1/lib/pkgconfig"

の後に

 ./google-cloud-sdk/install.sh

を実行すると

Welcome to the Google Cloud CLI!

To help improve the quality of this product, we collect anonymized usage data
and anonymized stacktraces when crashes are encountered; additional information
is available at <https://cloud.google.com/sdk/usage-statistics>. This data is
handled in accordance with our privacy policy
<https://cloud.google.com/terms/cloud-privacy-notice>. You may choose to opt in this
collection now (by choosing 'Y' at the below prompt), or at any time in the
future by running the following command:

    gcloud config set disable_usage_reporting false

Do you want to help improve the Google Cloud CLI (y/N)?  

となる
メッセージを検索し

gcloud CLI をインストールする
を参考に
これは
N
でよいらしい

ちなみに日本語訳は
Google Cloud CLI へようこそ。

この製品の品質向上に役立てるため、当社は匿名化された使用状況データを収集します。
クラッシュが発生した場合は匿名化されたスタックトレース。追加情報
で入手できます。このデータは
弊社のプライバシーポリシーに従って取り扱われます
。これを選択することもできます
今すぐ (以下のプロンプトで「Y」を選択)、またはいつでも収集できます。
次のコマンドを実行して、将来のことを確認します。

gcloud config set disable_usage_reporting false

Google Cloud CLI の改善に協力したいと思いますか (y/N)?

どうやらデータ収集に同意するか
ということらしい

次に

Your current Google Cloud CLI version is: 477.0.0
The latest available version is: 484.0.0

┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                                     Components                                                     │
├──────────────────┬──────────────────────────────────────────────────────┬──────────────────────────────┬───────────┤
│      Status      │                         Name                         │              ID              │    Size   │
├──────────────────┼──────────────────────────────────────────────────────┼──────────────────────────────┼───────────┤
│ Update Available │ BigQuery Command Line Tool                           │ bq                           │   1.7 MiB │
│ Update Available │ Cloud Storage Command Line Tool                      │ gsutil                       │  11.3 MiB │
│ Update Available │ Google Cloud CLI Core Libraries                      │ core                         │  19.1 MiB │
│ Not Installed    │ App Engine Go Extensions                             │ app-engine-go                │   4.5 MiB │
│ Not Installed    │ Appctl                                               │ appctl                       │  18.5 MiB │
│ Not Installed    │ Artifact Registry Go Module Package Helper           │ package-go-module            │   < 1 MiB │
│ Not Installed    │ Cloud Bigtable Command Line Tool                     │ cbt                          │  17.0 MiB │
│ Not Installed    │ Cloud Bigtable Emulator                              │ bigtable                     │   7.0 MiB │
│ Not Installed    │ Cloud Datastore Emulator                             │ cloud-datastore-emulator     │  36.2 MiB │
│ Not Installed    │ Cloud Firestore Emulator                             │ cloud-firestore-emulator     │  45.2 MiB │
│ Not Installed    │ Cloud Pub/Sub Emulator                               │ pubsub-emulator              │  63.7 MiB │
│ Not Installed    │ Cloud Run Proxy                                      │ cloud-run-proxy              │  11.3 MiB │
│ Not Installed    │ Cloud SQL Proxy v2                                   │ cloud-sql-proxy              │  13.2 MiB │
│ Not Installed    │ Google Container Registry's Docker credential helper │ docker-credential-gcr        │           │
│ Not Installed    │ Kustomize                                            │ kustomize                    │   7.4 MiB │
│ Not Installed    │ Log Streaming                                        │ log-streaming                │  11.9 MiB │
│ Not Installed    │ Minikube                                             │ minikube                     │  34.8 MiB │
│ Not Installed    │ Nomos CLI                                            │ nomos                        │  30.1 MiB │
│ Not Installed    │ On-Demand Scanning API extraction helper             │ local-extract                │  13.7 MiB │
│ Not Installed    │ Skaffold                                             │ skaffold                     │  22.8 MiB │
│ Not Installed    │ Terraform Tools                                      │ terraform-tools              │  63.6 MiB │
│ Not Installed    │ anthos-auth                                          │ anthos-auth                  │  20.9 MiB │
│ Not Installed    │ config-connector                                     │ config-connector             │  88.7 MiB │
│ Not Installed    │ enterprise-certificate-proxy                         │ enterprise-certificate-proxy │   8.3 MiB │
│ Not Installed    │ gcloud Alpha Commands                                │ alpha                        │   < 1 MiB │
│ Not Installed    │ gcloud Beta Commands                                 │ beta                         │   < 1 MiB │
│ Not Installed    │ gcloud app Java Extensions                           │ app-engine-java              │ 127.8 MiB │
│ Not Installed    │ gcloud app Python Extensions                         │ app-engine-python            │   5.0 MiB │
│ Not Installed    │ gcloud app Python Extensions (Extra Libraries)       │ app-engine-python-extras     │   < 1 MiB │
│ Not Installed    │ gke-gcloud-auth-plugin                               │ gke-gcloud-auth-plugin       │   4.0 MiB │
│ Not Installed    │ istioctl                                             │ istioctl                     │  24.8 MiB │
│ Not Installed    │ kpt                                                  │ kpt                          │  13.8 MiB │
│ Not Installed    │ kubectl                                              │ kubectl                      │   < 1 MiB │
│ Not Installed    │ kubectl-oidc                                         │ kubectl-oidc                 │  20.9 MiB │
│ Not Installed    │ pkg                                                  │ pkg                          │           │
│ Installed        │ Google Cloud CRC32C Hash Tool                        │ gcloud-crc32c                │   1.2 MiB │
└──────────────────┴──────────────────────────────────────────────────────┴──────────────────────────────┴───────────┘
To install or remove components at your current SDK version [477.0.0], run:
  $ gcloud components install COMPONENT_ID
  $ gcloud components remove COMPONENT_ID

To update your SDK installation to the latest version [484.0.0], run:
  $ gcloud components update


Modify profile to update your $PATH and enable shell command completion?

Do you want to continue (Y/n)?  

これを訳そうとしたけど
Google 翻訳は3900文字以上だとできなかった

To install or remove components at your current SDK version [477.0.0], run:
  $ gcloud components install COMPONENT_ID
  $ gcloud components remove COMPONENT_ID

To update your SDK installation to the latest version [484.0.0], run:
  $ gcloud components update


Modify profile to update your $PATH and enable shell command completion?

Do you want to continue (Y/n)?  

だけにして翻訳

現在の SDK バージョン [477.0.0] でコンポーネントをインストールまたは削除するには、次を実行します。
$ gcloud コンポーネントのインストール COMPONENT_ID
$ gcloud コンポーネントは COMPONENT_ID を削除します

SDK インストールを最新バージョン [484.0.0] に更新するには、次を実行します。
$ gcloud コンポーネントの更新

プロファイルを変更して $PATH を更新し、シェル コマンド補完を有効にしますか?

続行しますか (Y/n)?

これは
Y
でよいらしい

The Google Cloud SDK installer will now prompt you to update an rc file to bring
 the Google Cloud CLIs into your environment.

Enter a path to an rc file to update, or leave blank to use 
[/Users/snowpool/.zshrc]:  

の翻訳は

Google Cloud SDK インストーラは、rc ファイルを更新して、
Google Cloud CLI を環境に導入します。

更新する rc ファイルへのパスを入力するか、空白のままにして使用します
[/ユーザー/snowpool/.zshrc]:

これは
Enterキーにした

Backing up [/Users/snowpool/.zshrc] to [/Users/snowpool/.zshrc.backup].
[/Users/snowpool/.zshrc] has been updated.

==> Start a new shell for the changes to take effect.


Google Cloud CLI works best with Python 3.11 and certain modules.

Download and run Python 3.11 installer? (Y/n)?  

の翻訳は

[/Users/snowpool/.zshrc] を [/Users/snowpool/.zshrc.backup] にバックアップしています。
[/Users/snowpool/.zshrc]が更新されました。

==> 変更を有効にするために新しいシェルを開始します。

Google Cloud CLI は、Python 3.11 および特定のモジュールで最適に動作します。

Python 3.11 インストーラーをダウンロードして実行しますか? (はい/いいえ)?
なので
Y
にする

Running Python 3.11 installer, you may be prompted for sudo password...
Password:

となるので
Macのパスワードを入れる

あとは処理が自動で行われ

installer: Package name is Python
installer: Installing at base path /

installer: The install was successful.
Setting up virtual environment
Creating virtualenv...
Installing modules...
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 89.7/89.7 kB 2.4 MB/s eta 0:00:00
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Preparing metadata (pyproject.toml) ... done
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 59.0/59.0 kB 5.0 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 10.4/10.4 MB 7.2 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 163.0/163.0 kB 3.4 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.9/2.9 MB 7.4 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 182.4/182.4 kB 8.7 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 117.6/117.6 kB 6.5 MB/s eta 0:00:00
  Building wheel for crcmod (pyproject.toml) ... done


Updates are available for some Google Cloud CLI components.  To install them,
please run:
  $ gcloud components update

Virtual env enabled.

For more information on how to get started, please visit:
  https://cloud.google.com/sdk/docs/quickstarts

となる

source ~/.zshrc

を実行すれば

gcloud -v

が実行できるようになる

結果は

Google Cloud SDK 477.0.0
bq 2.1.4
core 2024.05.17
gcloud-crc32c 1.0.0
gsutil 5.29
Updates are available for some Google Cloud CLI components.  To install them,
please run:
  $ gcloud components update

次はgcloudの初期化をする

Markdownの記述メモとGithub へソースコード公開

Markdownの記述メモとGithub へソースコード公開

Markdownの書き方

を参考に

# 見出しレベル1
## 見出しレベル2
### 見出しレベル3
#### 見出しレベル4
##### 見出しレベル5

見出しレベル1
=========

見出しレベル2
---------

レベル1は
H1

と同じ

ソースコードは
バッククォートを使ってコードを囲む

改行は行末にスペースを2つ入れる

URLはそのままでOK

# mail_voice
Read unread Gmail text with URL removed. If there is a link in the text, open it with selenium and download the PDF.

特別支援学校のお知らせがCocooによりメールで送られてくるため  
Gmailでラベルを作成し、未読のメールを読み上げるようにしています。  
メール内の本文をvoicevox で読み上げ、  
文章内にURLがある場合 selenimでダウンロードし  
PDFの文字数が100文字以下なら読み上げ、  
それ以上ならPDFを確認するように音声が流れます。

## 動作環境
M1 MacbookAir 16GB で動作しています、  

音声の作成に voicevox の docker が必要になります  
`docker pull voicevox/voicevox_engine:cpu-ubuntu20.04-latest`  
で取得しています

動作させるには

バックグランドでの起動で
-d オプションをつけて  
`docker run -d  -p '192.168.1.69:50021:50021' voicevox/voicevox_engine:cpu-ubuntu20.04-latest`  
というように起動させます  
IPアドレス部分はご自身のマシンのIPに変えてください

Gmailを操作するためAPIとtoken.jsonが必要になります  
https://developers.google.com/gmail/api/quickstart/python?hl=ja  
を参考にAPIを使用可能にし、token.jsonを取得し同一ディレクトリに設置してください  

config.iniの中にGmailラベルの設定と  
dockerマシンのIPアドレスの設定  
次の顔検出までの設定時間があります  

それぞれの使用環境でセットしてください

として保存

次に
GitHubでパスワード認証が廃止されたため、
HTTPSを使ってリモートリポジトリにアクセスする際にはパーソナルアクセストークン(PAT)を使用するか、
SSHキー認証を使用する必要がある

今回はSSHキー認証を使う

ssh-keygen -t ed25519 -C “メールアドレス”

でパスフレーズを入力

cat id_ed25519

でファイルの中身が見れる

GtHubにログインし、右上のプロフィールアイコンをクリックして「Settings」に進み
「SSH and GPG keys」をクリックし、「New SSH key」ボタンをクリックし
Title」にキーの名前を入力し、「Key」フィールドに公開キーの内容をペースト

Add SSH key」をクリックしてキーを登録

しかし登録がされなかった

再度試す

cat ~/.ssh/id_ed25519.pub | pbcopy

でクリップボードにコピーした値を使ってみた

これが正しい値だった

これにより
SSHで git clone しようとした時の

You don't have any public SSH keys in your GitHub account. You can add a new public key, or try cloning this repository via HTTPS.

が消える

git clone git@github.com:Snowpooll/mail_voice.git


設定したSSHのパスフレーズを入力すれば
Git clone が実行される

次に gitignore と requirements.txtを作成する

 vim .gitignore

でファイルを作成

__pycache__/
query.json
token.json
downloaded_file.pdf
notice.wav
notice_pdf.wav
audio_output.wav
email_body.txt

として保存

次に

vim requirements.txt

でファイルを作成

中身は

PyMuPDF
playsound
configparser
pygame
google-api-python-client
google-auth-oauthlib
google-auth-httplib2
python-dateutil
opencv-python
selenium
requests

あとは

git add .
 git commit -m "add source code"
git push -u origin main

で公開

先にコードをアップして
READMEは後で書くことも可能

在庫管理のための検出画像ディレクトリと推論モデルのディレクトリ設定

在庫管理のための検出画像ディレクトリと推論モデルのディレクトリ設定

モデルと
推論する画像を格納するディレクトリを
設定ファイルconfig.iniで指定しておき
切り替えを簡単にできるようにする

これはモデルを今後作成しなおすのと
画像の対象をwebカメラで撮影したものにするか
もしくはリアルタイムで監視したものにするかを切り替えるため

mkdir inventory_images

で画像ファイルの置き場所を作成

vim config.ini

で設定ファイルを作成

[Settings]
model_path = inventory_model/best.pt
image_directory = inventory_images

として保存

count_inventory.py
の中身を
import json
from ultralytics import YOLO
from collections import defaultdict

# JSONファイルからクラスラベルのマッピングを読み込み
with open('label_mapping.json', 'r', encoding='utf-8') as f:
    label_mapping = json.load(f)

# YOLOv8モデルのロード
model = YOLO('inventory_model/best.pt')  # ここで適切なモデルを選択

# 画像のロード
image_path = 'path_to_your_image.jpg'
image = cv2.imread(image_path)

# 画像の検出
results = model(image)

# 検出結果の取得
detections = results[0]  # 最初の結果を取得
classes = detections.boxes.cls

# 検出物体のカウント
object_counts = defaultdict(int)
for cls in classes:
    class_label = model.names[int(cls)]
    if class_label in label_mapping:
        label = label_mapping[class_label]
    else:
        label = class_label
    object_counts[label] += 1

# 検出結果の表示
for label, count in object_counts.items():
    print(f'{label}: {count}個')

から

import json
import cv2
import configparser
from ultralytics import YOLO
from collections import defaultdict
from line_notify import send_line_notify  # インポートを追加
from datetime import datetime
from inventory_database_module 
 import save_detection_to_db  # データベース保存用の関数をインポート
import os

# 設定ファイルの読み込み
config = configparser.ConfigParser()
config.read('config.ini')

# 設定ファイルからモデルパスと画像ディレクトリを取得
model_path = config['Settings']['model_path']
image_directory = config['Settings']['image_directory']

# ラベルマッピングファイルのパス
label_mapping_path = 'label_mapping.json'

# JSONファイルからクラスラベルのマッピングを読み込み
with open(label_mapping_path, 'r', encoding='utf-8') as f:
    label_mapping = json.load(f)

# YOLOv8モデルのロード
model = YOLO(model_path)  # 設定ファイルからモデルパスを使用

# 画像ディレクトリ内の全画像ファイルを処理
for image_filename in os.listdir(image_directory):
    image_path = os.path.join(image_directory, image_filename)
    if os.path.isfile(image_path) and image_path.lower().endswith(('.png', '.jpg', '.jpeg')):
        # 画像のロード
        image = cv2.imread(image_path)

        # 画像の検出
        results = model(image, save=True, conf=0.2, iou=0.5)

        # 検出結果の取得
        detections = results[0]  # 最初の結果を取得
        classes = detections.boxes.cls

        # 検出物体のカウント
        object_counts = defaultdict(int)
        for cls in classes:
            class_label = model.names[int(cls)]
            if class_label in label_mapping:
                label = label_mapping[class_label]
            else:
                label = class_label
            object_counts[label] += 1

        # 検出結果のフィルタリング(1以下のもの)
        filtered_object_counts = {label: count for label, count in object_counts.items() if count <= 1}

        # フィルタリングされた検出結果のメッセージ生成
        message_lines = [f'{label}: {count}個' for label, count in filtered_object_counts.items()]
        message = '\n'.join(message_lines)

        # 現在の時刻を取得
        current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        message = f"{message}\n\nMessage sent at: {current_time}"

        # 検出結果の表示
        for line in message_lines:
            print(line)

        # LINE Notifyにメッセージを送信(フィルタリングされた結果のみ)
        if message_lines:
            send_line_notify(message)
            save_detection_to_db(filtered_object_counts)  # データベースに検出結果を保存
        else:
            print("No objects with counts of 1 or less detected in file:", image_filename)

へ変更

試しに

cp data_bak/Baskulin4.jpg inventory_images

でデータを写し

python count_inventory.py

を実行すると

0: 640x512 1 baskulin, 131.0ms
Speed: 5.6ms preprocess, 131.0ms inference, 6.6ms postprocess per image at shape (1, 3, 640, 512)
Results saved to runs/detect/predict22
バスクリン: 1個
File: runs/detect/predict22/image0.jpg
200
{"status":200,"message":"ok"}

というようにLINEへ送信される

とりあえずここまでできたので
githubで公開し
モデルは roboflowなどを使って改良して後々公開する

yolov8の検出結果のDB格納

検出結果のDB格納

vim create_table.py

を作成

import sqlite3

def create_table():
    conn = sqlite3.connect('detections.db')
    cursor = conn.cursor()

    # テーブルを作成
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS detections (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            label TEXT NOT NULL,
            count INTEGER NOT NULL,
            timestamp TEXT NOT NULL
        )
    ''')

    conn.commit()
    conn.close()

if __name__ == '__main__':
    create_table()

これを実行し
DBを作成

次にDBへ保存するモジュールの作成

vim inventory_database_module.py

でファイルを作成

import sqlite3
from datetime import datetime

def save_detection_to_db(detections):
    conn = sqlite3.connect('detections.db')
    cursor = conn.cursor()

    # 現在の時刻を取得
    current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

    # 検出結果をテーブルに挿入
    for label, count in detections.items():
        cursor.execute('''
            INSERT INTO detections (label, count, timestamp)
            VALUES (?, ?, ?)
        ''', (label, count, current_time))

    conn.commit()
    conn.close()

として保存

import argparse
import json
import cv2
from ultralytics import YOLO
from collections import defaultdict
from line_notify import send_line_notify  # インポートを追加
from datetime import datetime
from inventory_database_module import save_detection_to_db  # データベース保存用の関数をインポート

# コマンドライン引数の解析
parser = argparse.ArgumentParser(description="YOLOv8 Object Detection")
parser.add_argument('image_path', type=str, help='Path to the input image file')
args = parser.parse_args()

# ラベルマッピングファイルのパス
label_mapping_path = 'label_mapping.json'

# JSONファイルからクラスラベルのマッピングを読み込み
with open(label_mapping_path, 'r', encoding='utf-8') as f:
    label_mapping = json.load(f)

# YOLOv8モデルのロード
model = YOLO('inventory_model/best.pt')  # ここで適切なモデルを選択

# 画像のロード
image = cv2.imread(args.image_path)

# 画像の検出
results = model(image, save=True, conf=0.1, iou=0.5)

# 検出結果の取得
detections = results[0]  # 最初の結果を取得
classes = detections.boxes.cls

# 検出物体のカウント
object_counts = defaultdict(int)
for cls in classes:
    class_label = model.names[int(cls)]
    if class_label in label_mapping:
        label = label_mapping[class_label]
    else:
        label = class_label
    object_counts[label] += 1

# 検出結果のフィルタリング(1以下のもの)
filtered_object_counts = {label: count for label, count in object_counts.items() if count <= 1}

# フィルタリングされた検出結果のメッセージ生成
message_lines = [f'{label}: {count}個' for label, count in filtered_object_counts.items()]
message = '\n'.join(message_lines)

# 現在の時刻を取得
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
message = f"{message}\n在庫チェックの時刻: {current_time}"

# 検出結果の表示
for line in message_lines:
    print(line)

# LINE Notifyにメッセージを送信(フィルタリングされた結果のみ)
if message_lines:
    send_line_notify(message)
    save_detection_to_db(filtered_object_counts)  # データベースに検出結果を保存
else:
    print("No objects with counts of 1 or less detected.")

というように
結果をDBに保存し
在庫チェックの時刻も送信するようにコード変更

なお実行した後に
DBの中身を見るには

vim view_detections.py

import sqlite3

def view_detections(db_path='detections.db'):
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()

    # テーブルの内容を取得
    cursor.execute('SELECT * FROM detections')
    rows = cursor.fetchall()

    # カラム名を取得
    column_names = [description[0] for description in cursor.description]

    # 結果を表示
    print(f"{' | '.join(column_names)}")
    print("-" * 50)
    for row in rows:
        print(" | ".join(str(value) for value in row))

    conn.close()

if __name__ == '__main__':
    view_detections()

として保存

python view_detections.py

を実行すると

id | label | count | timestamp
--------------------------------------------------
1 | バスクリン | 1 | 2024-07-07 06:45:47
2 | バスクリン | 1 | 2024-07-07 06:50:42
3 | バスクリン | 1 | 2024-07-07 06:51:43

となり検出結果の確認ができる

認識精度が低いため
精度を0.1まで下げないと認識しないし
並べた時の複数の検出ができていない

とりあえず指定ディレクトリの画像から検出するようにコード変更する

LINE notifyのモジュール化

LINE notifyのモジュール化

別のメソッドでも使えるようにモジュール化する
また

message = 'ファイルパス自動取得テスト' 

の部分は
他のプログラムで
生成された文字列を受け取って実行するようにコードを変更する

vim line_notify.py

import requests
import os
from PIL import Image
from io import BytesIO
from utils import load_config, get_latest_directory, get_image_files

def resize_image_if_needed(image_data, max_size=3 * 1024 * 1024):
    if len(image_data) > max_size:
        image = Image.open(BytesIO(image_data))
        new_size = (image.width // 2, image.height // 2)
        image = image.resize(new_size, Image.LANCZOS)

        output = BytesIO()
        image_format = image.format if image.format else 'JPEG'
        image.save(output, format=image_format)
        return output.getvalue()
    return image_data

def send_line_notify(message, config_path='config.json'):
    # 設定ファイルを読み込む
    config = load_config(config_path)

    # 設定ファイルからトークンとディレクトリパスを取得
    token = config['token']
    base_path = config['image_file_path']

    # 最新のpredictディレクトリを取得
    latest_dir = get_latest_directory(base_path)
    image_files = get_image_files(latest_dir)

    url = 'https://notify-api.line.me/api/notify'

    headers = {'Authorization': f"Bearer {token}"}
    params = {'message': message}

    # 最新のpredictディレクトリ内の全ての画像ファイルに対してLINE Notify APIにリクエストを送信
    for image_file_path in image_files:
        with open(image_file_path, 'rb') as img_file:
            img_data = img_file.read()
            img_data = resize_image_if_needed(img_data)

            # ファイルデータをバイトデータとして用意
            files = {'imageFile': BytesIO(img_data)}
            files['imageFile'].name = os.path.basename(image_file_path)

            # LINE Notify APIにリクエストを送信
            res = requests.post(url, headers=headers, params=params, files=files)

            # レスポンスを出力
            print(f"File: {image_file_path}")
            print(res.status_code)
            print(res.text)

とりあえずこれを使えるかテストする

import argparse
import json
import cv2
from ultralytics import YOLO
from collections import defaultdict

# コマンドライン引数の解析
parser = argparse.ArgumentParser(description="YOLOv8 Object Detection")
parser.add_argument('image_path', type=str, help='Path to the input image file')
args = parser.parse_args()

# ラベルマッピングファイルのパス
label_mapping_path = 'label_mapping.json'

# JSONファイルからクラスラベルのマッピングを読み込み
with open(label_mapping_path, 'r', encoding='utf-8') as f:
    label_mapping = json.load(f)

# YOLOv8モデルのロード
model = YOLO('inventory_model/best.pt')  # ここで適切なモデルを選択

# 画像のロード
image = cv2.imread(args.image_path)

# 画像の検出
results = model(image, save=True, conf=0.2, iou=0.5)

# 検出結果の取得
detections = results[0]  # 最初の結果を取得
classes = detections.boxes.cls

# 検出物体のカウント
object_counts = defaultdict(int)
for cls in classes:
    class_label = model.names[int(cls)]
    if class_label in label_mapping:
        label = label_mapping[class_label]
    else:
        label = class_label
    object_counts[label] += 1

# 検出結果の表示
for label, count in object_counts.items():
    print(f'{label}: {count}個')

の中で呼び出すようにする

import argparse
import json
import cv2
from ultralytics import YOLO
from collections import defaultdict
from line_notify import send_line_notify  # インポートを追加

# コマンドライン引数の解析
parser = argparse.ArgumentParser(description="YOLOv8 Object Detection")
parser.add_argument('image_path', type=str, help='Path to the input image file')
args = parser.parse_args()

# ラベルマッピングファイルのパス
label_mapping_path = 'label_mapping.json'

# JSONファイルからクラスラベルのマッピングを読み込み
with open(label_mapping_path, 'r', encoding='utf-8') as f:
    label_mapping = json.load(f)

# YOLOv8モデルのロード
model = YOLO('inventory_model/best.pt')  # ここで適切なモデルを選択

# 画像のロード
image = cv2.imread(args.image_path)

# 画像の検出
results = model(image, save=True, conf=0.2, iou=0.5)

# 検出結果の取得
detections = results[0]  # 最初の結果を取得
classes = detections.boxes.cls

# 検出物体のカウント
object_counts = defaultdict(int)
for cls in classes:
    class_label = model.names[int(cls)]
    if class_label in label_mapping:
        label = label_mapping[class_label]
    else:
        label = class_label
    object_counts[label] += 1

# 検出結果のメッセージ生成
message_lines = [f'{label}: {count}個' for label, count in object_counts.items()]
message = '\n'.join(message_lines)

# 検出結果の表示
for line in message_lines:
    print(line)

# LINE Notifyにメッセージを送信
send_line_notify(message)

これを

python count_inventory_terminal.py data_bak/Baskulin4.jpg

で実行すると

0: 640x512 1 baskulin, 125.4ms
Speed: 7.7ms preprocess, 125.4ms inference, 7.6ms postprocess per image at shape (1, 3, 640, 512)
Results saved to runs/detect/predict4
バスクリン: 1個
File: runs/detect/predict4/image0.jpg
200
{"status":200,"message":"ok"}

となり画像つきメッセージが送信される

次は在庫の数が1以下のものをリストにして送信するようにする

import argparse
import json
import cv2
from ultralytics import YOLO
from collections import defaultdict
from line_notify import send_line_notify  # インポートを追加

# コマンドライン引数の解析
parser = argparse.ArgumentParser(description="YOLOv8 Object Detection")
parser.add_argument('image_path', type=str, help='Path to the input image file')
args = parser.parse_args()

# ラベルマッピングファイルのパス
label_mapping_path = 'label_mapping.json'

# JSONファイルからクラスラベルのマッピングを読み込み
with open(label_mapping_path, 'r', encoding='utf-8') as f:
    label_mapping = json.load(f)

# YOLOv8モデルのロード
model = YOLO('inventory_model/best.pt')  # ここで適切なモデルを選択

# 画像のロード
image = cv2.imread(args.image_path)

# 画像の検出
results = model(image, save=True, conf=0.2, iou=0.5)

# 検出結果の取得
detections = results[0]  # 最初の結果を取得
classes = detections.boxes.cls

# 検出物体のカウント
object_counts = defaultdict(int)
for cls in classes:
    class_label = model.names[int(cls)]
    if class_label in label_mapping:
        label = label_mapping[class_label]
    else:
        label = class_label
    object_counts[label] += 1

# 検出結果のフィルタリング(1以下のもの)
filtered_object_counts = {label: count for label, count in object_counts.items() if count <= 1}

# フィルタリングされた検出結果のメッセージ生成
message_lines = [f'{label}: {count}個' for label, count in filtered_object_counts.items()]
message = '\n'.join(message_lines)

# 検出結果の表示
for line in message_lines:
    print(line)

# LINE Notifyにメッセージを送信(フィルタリングされた結果のみ)
if message:
    send_line_notify(message)
else:
    print("No objects with counts of 1 or less detected.")

これで今度は

python count_inventory_terminal.py data_bak/potato_starch1.jpg 

として検出されない時には

0: 640x512 (no detections), 123.0ms
Speed: 5.7ms preprocess, 123.0ms inference, 5.4ms postprocess per image at shape (1, 3, 640, 512)
Results saved to runs/detect/predict6
No objects with counts of 1 or less detected.

となって
LINE送信はされなくなる

今回の画像はモデルの学習不足のためか
片栗粉の検出ができなかったので
それを認識できない場合のテストに使った

しかし、画像読み取りエラーなどを考慮し
今後何らかのアクションを取るようにした方が良いかもしれない

エラーログ以外のものを考えるようにする

また、送信するタイミングは、在庫数が1以下になった時に送るようにしました。

この場合、画像が検出できなかったりした時に判定ができないため
今後の課題とします
解決方法としては、検出結果をDBへ格納しておき
実行したタイムスタンプも記録、検出結果が0の時にはアラートを飛ばすなどがありそうです

とりあえず、ターミナル実行のみの状態なので
今後はどこから画像を撮ってくるのか、またwebカメラで行うのか、それとも
ラズパイゼロなどで撮影した画像を使うのか、それを考えてからまた改良していこうと思います

LINE通知の時の画像サイズ変更

LINE通知の時の画像サイズ変更

3M以上の画像サイズになると

File: runs/detect/predict3/image0.jpg
400
{"status":400,"message":"Image size must be less than 3MB."}

となるため、画像ファイルの大きさを変更するプログラムが必要

なお画像については

results = model(image, save=True, conf=0.2, iou=0.5)

というように
save=True をつければ検出結果が出力されるので
その画像を使う

画像サイズが3MB以下になるように画像を1/4にリサイズして送信するようにコード変更

import requests
import os
from utils import load_config, get_latest_directory, get_image_files

# 設定ファイルを読み込む
config = load_config('config.json')

# 設定ファイルからトークンとディレクトリパスを取得
token = config['token']
base_path = config['image_file_path']

# 最新のpredictディレクトリを取得
latest_dir = get_latest_directory(base_path)
image_files = get_image_files(latest_dir)

url = 'https://notify-api.line.me/api/notify'
message = 'ファイルパス自動取得テスト'

headers = {'Authorization': f"Bearer {token}"}
params = {'message': message}

# 最新のpredictディレクトリ内の全ての画像ファイルに対してLINE Notify APIにリクエストを送信
for image_file_path in image_files:
    files = {'imageFile': open(image_file_path, 'rb')}
    
    # LINE Notify APIにリクエストを送信
    res = requests.post(url, headers=headers, params=params, files=files)

    # レスポンスを出力
    print(f"File: {image_file_path}")
    print(res.status_code)
    print(res.text)

import requests
import os
from PIL import Image
from io import BytesIO
from utils import load_config, get_latest_directory, get_image_files

# 設定ファイルを読み込む
config = load_config('config.json')

# 設定ファイルからトークンとディレクトリパスを取得
token = config['token']
base_path = config['image_file_path']

# 最新のpredictディレクトリを取得
latest_dir = get_latest_directory(base_path)
image_files = get_image_files(latest_dir)

url = 'https://notify-api.line.me/api/notify'
message = 'ファイルパス自動取得テスト'

headers = {'Authorization': f"Bearer {token}"}
params = {'message': message}

# 最新のpredictディレクトリ内の全ての画像ファイルに対してLINE Notify APIにリクエストを送信
for image_file_path in image_files:
    with open(image_file_path, 'rb') as img_file:
        img_data = img_file.read()
        
        # 画像ファイルのサイズをチェック
        if len(img_data) > 3 * 1024 * 1024:  # 3MB
            # 画像をリサイズ
            image = Image.open(BytesIO(img_data))
            new_size = (image.width // 2, image.height // 2)
            image = image.resize(new_size, Image.ANTIALIAS)
            
            # リサイズした画像をバイトデータに変換
            output = BytesIO()
            image.save(output, format=image.format)
            img_data = output.getvalue()
        
        # ファイルデータをバイトデータとして用意
        files = {'imageFile': BytesIO(img_data)}
        files['imageFile'].name = os.path.basename(image_file_path)
        
        # LINE Notify APIにリクエストを送信
        res = requests.post(url, headers=headers, params=params, files=files)

        # レスポンスを出力
        print(f"File: {image_file_path}")
        print(res.status_code)
        print(res.text)

としたが

/Users/snowpool/aw10s/inventory/line_order.py:34: DeprecationWarning: ANTIALIAS is deprecated and will be removed in Pillow 10 (2023-07-01). Use LANCZOS or Resampling.LANCZOS instead.
  image = image.resize(new_size, Image.ANTIALIAS)
Traceback (most recent call last):
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/PIL/Image.py", line 2408, in save
    format = EXTENSION[ext]
KeyError: ''

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/snowpool/aw10s/inventory/line_order.py", line 38, in <module>
    image.save(output, format=image.format)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/PIL/Image.py", line 2411, in save
    raise ValueError(msg) from e
ValueError: unknown file extension: 

となる

これは
ANTIALIASの非推奨:ANTIALIASがPillow 10で非推奨となり、代わりにLANCZOSを使用する必要がある

画像の形式が不明:image.saveメソッドに指定された形式が正しく解釈されていないため、KeyErrorが発生しています。これは、image.formatが正しく設定されていないか、空であるため
の2つが原因

import requests
import os
from PIL import Image
from io import BytesIO
from utils import load_config, get_latest_directory, get_image_files

# 設定ファイルを読み込む
config = load_config('config.json')

# 設定ファイルからトークンとディレクトリパスを取得
token = config['token']
base_path = config['image_file_path']

# 最新のpredictディレクトリを取得
latest_dir = get_latest_directory(base_path)
image_files = get_image_files(latest_dir)

url = 'https://notify-api.line.me/api/notify'
message = 'ファイルパス自動取得テスト'

headers = {'Authorization': f"Bearer {token}"}
params = {'message': message}

# 最新のpredictディレクトリ内の全ての画像ファイルに対してLINE Notify APIにリクエストを送信
for image_file_path in image_files:
    with open(image_file_path, 'rb') as img_file:
        img_data = img_file.read()
        
        # 画像ファイルのサイズをチェック
        if len(img_data) > 3 * 1024 * 1024:  # 3MB
            # 画像をリサイズ
            image = Image.open(BytesIO(img_data))
            new_size = (image.width // 2, image.height // 2)
            image = image.resize(new_size, Image.LANCZOS)
            
            # リサイズした画像をバイトデータに変換
            output = BytesIO()
            image_format = image.format if image.format else 'JPEG'  # デフォルトでJPEG形式を設定
            image.save(output, format=image_format)
            img_data = output.getvalue()
        
        # ファイルデータをバイトデータとして用意
        files = {'imageFile': BytesIO(img_data)}
        files['imageFile'].name = os.path.basename(image_file_path)
        
        # LINE Notify APIにリクエストを送信
        res = requests.post(url, headers=headers, params=params, files=files)

        # レスポンスを出力
        print(f"File: {image_file_path}")
        print(res.status_code)
        print(res.text)

とすることで

File: runs/detect/predict3/image0.jpg
200
{"status":200,"message":"ok"}

となり、元の画像サイズが大きくても問題なく送信できるようになった

LINE Notify を通知で使う

LINEで通知できるようにする

在庫管理をできるようにしたら
足りないものを知らせる機能が必要

LINEで買い物リストとして昼ぐらいに送信すれば
帰りに購入して帰ることができる

過去記事を参考に
LINE Messasging API でメッセージ送信

を参考にリンクをしたら

LINE Business ID
になってしまうので
再度調べることにする

LINE: LINE Notifyを用いてWindowsのcurlコマンドからメッセージを投稿する
を参考に再度設定をしていく

スマホのLINEアプリで
トーク > トークルームの作成 > グループ

友達は誰も選択せずに次へ

次に友達をグループに追加があるけど
デフォルトで友達をグループに自動で追加がチェックされているので
チェックを外す

グループ名は買い物リスト
とした

次にLINE Notifyにログインする
https://notify-bot.line.me/ja/

ログインの時にQRコードからログインできるので
スマホのLINEアプリでQRコードを読み取る
もしくはスマホのカメラアプリでQRコードを読み取ると
LINEアプリでQRコードを読み取るように出るので
そのまま実行していくと認証画面になり
PCの画面に表示された数字をスマホで打ち込めば
ログインできる

ログインできたらトークンを発行する

マイページ > アクセストークンの発行

トークンを発行する
をクリックし
トークン名を入力し
通知を送信するトークルームを選択

今回は両方とも
買い物リストを選択

これでトークンが発行される

次にスマホで
買い物リストの
トークルームを開き
設定 > 招待 で
LINE notifyを選択し招待する

ここへはcurlコマンドでメッセージを送信できる

https://notify-bot.line.me/doc/ja/
のサンプルは

 curl -X POST -H 'Authorization: Bearer <access_token>' -F 'message=foobar' \
https://notify-api.line.me/api/notify
{"status":200,"message":"ok"}

 curl -v -X POST -H 'Authorization: Bearer invalidtoken' -F 'message=foobar' \
https://notify-api.line.me/api/notify
{"status":401,"message":"Invalid access token"}

https://qiita.com/frozencatpisces/items/679d66ab1d617b7a40cb#1-投稿先トークルームの作成
では

curl -X POST -H "Authorization: Bearer 発行したトークン" -F "message=foobar" https://notify-api.line.me/api/notify

これをリストにする場合は複数行必要なので
LINE Notify で curl で改行する
https://blog.framinal.life/entry/2023/06/14/151933
を参考に

URLエンコーディングされた改行文字(%0A) に変換して送ることでできそう

message="こんにちは\n元気ですか?\n\n"

# Convert newline characters to URL-encoded form
message_encoded=$(echo -e $message | awk '{printf "%s%%0A", $0}')

curl -X POST -H "Authorization: Bearer XXXXXX" --data-binary "message=$message_encoded" https://notify-api.line.me/api/notify

ちょっと古い情報で3年前のだと

LINE NotifyからのLINE通知を改行する方法【Python/LINE Notify(API)】
だと
Lineで通知する文章を改行したい場合、「\n」を入れると改行できるらしい

send_contents = f'\n今日は\n{strftime}({day_of_the_week[weekday]})です。'

また

send_contents = '\n今日は\n' + str(strftime) + '(' + str(day_of_the_week[weekday]) + ')です。'

というようにしてもOK

“Line Notify”を利用してPythonでLineに通知を送る
では
requesta
を使っている

pip install requests

テキストだけなら

import requests

url = 'https://notify-api.line.me/api/notify'

token = '発行したトークン'
message = '通知したいメッセージ'

headers = {'Authorization': f"Bearer {token}"}
params = {'message': message}

requests.post(url, headers=headers, params=params)

テキストと画像付きなら

import requests

url = 'https://notify-api.line.me/api/notify'

token = '発行したトークン'
message = '通知したいテキスト'
image_file_path = 'イメージファイルパス'

headers = {'Authorization': f"Bearer {token}"}
params = {'message': message}
files = {'imageFile': open(image_file_path, 'rb')}

res = requests.post(url, headers=headers, params=params, files=files)

テキストの改行なら

message = 'ここで改行\n改行後のテキスト'

PythonでLINE Notifyを使ってみよう
によれば
・メッセージを改行したい場合は「\n」を挿入
・メッセージは最大1000文字まで

import requests
def notify(message):

        url = 'https://notify-api.line.me/api/notify'
        token = '発行されたトークン'
        headers = {'Authorization': 'Bearer ' + token}

        message = message
        params = {'message': message}

        requests.post(url, headers=headers, params=params)

if __name__ == '__main__':
    notify('テスト')

がサンプル

こちらもrequestを使用

[Python]LINEで天気を自動通知させてみた[初心者]
によれば
Webから天気情報を取得してLINEで自動通知をしてみました。定期実行までやります
では
Cronで定期実行

実行するコードは

import datetime
import urllib.request as req
import requests
from bs4 import BeautifulSoup
import re

#LINE notifyの設定を行う
url = "https://notify-api.line.me/api/notify"
access_token = '○○○○○'
headers = {'Authorization': 'Bearer ' + access_token}

#天気サイトから欲しい情報を取得する
url2 = "https://tenki.jp/forecast/3/17/4610/14100/"   #欲しい情報があるURLを指定
res = requests.get(url2)                              #上記URL情報を取得する
soup = BeautifulSoup(res.content, 'html.parser')      #取得した情報をhtmlで解析する

# 以下各種情報を取得
ddd = soup.find(class_="left-style")                  

telop = soup.find("p", class_="weather-telop").string

highlists = soup.find("dd",class_="high-temp temp")

lowlists = soup.find("dd",class_="low-temp temp")

ttt = soup.find(class_="rain-probability")

row=[]
for t in ttt:
    row.append(t)

# message変数に通知したい文を代入する 改行したい場合は "\n" とダブルクォテーションで囲う
message="\n" + ddd.text + "\n" + telop + "\n" + "最高 " + highlists.text + "\n" + "最低 " + lowlists.text + "\n"+ "---------" + "\n" +row[1].text +"\n" + "~6  : " + row[3].text + "\n" + "~12 : " + row[5].text +"\n" + "~18 : " + row[7].text +"\n" + "~24 : " + row[9].text +"\n" +"今日も元気に٩( 'ω' )و "

payload = {'message': message}
r = requests.post(url, headers=headers, params=payload,)

というように requestを使っている

あと
1人のユーザーにつき、1時間に通知できる回数は1000回まで
という縛りがあるが
買い物リストは1日1回程度だと思うし
カメラ画像からとして考えても3箇所程度だと思うので問題なし

とりあえずchatgptで調べた結果
Curl でも requestでも問題はなさそう

コードメンテを考えるとrequestsの方が良さそう

ということで

vim line_order.py

でファイルを作成し

vim config.json

で設定ファイルを作成

{
  "token": "発行したトークン",
  "image_file_path": "イメージファイルパス"
}
import requests
import json

# 設定ファイルを読み込む関数
def load_config(file_path):
    with open(file_path, 'r') as file:
        return json.load(file)

# 設定ファイルを読み込む
config = load_config('config.json')

# 設定ファイルからトークンとファイルパスを取得
token = config['token']
image_file_path = config['image_file_path']

url = 'https://notify-api.line.me/api/notify'
message = '通知したいテキスト'

headers = {'Authorization': f"Bearer {token}"}
params = {'message': message}
files = {'imageFile': open(image_file_path, 'rb')}

# LINE Notify APIにリクエストを送信
res = requests.post(url, headers=headers, params=params, files=files)

# レスポンスを出力
print(res.status_code)
print(res.text)


line_order.py
の内容を書き換えても

Traceback (most recent call last):
  File "/Users/snowpool/aw10s/inventory/line_order.py", line 21, in <module>
    files = {'imageFile': open(image_file_path, 'rb')}
IsADirectoryError: [Errno 21] Is a directory: 'image/'

となる

とりあえず画像を指定する

{
  "token": "発行したトークン",
  "image_file_path": "runs/detect/predict7/Baskulin1.jpg"
}

とすれば成功

改良点としては
メッセージの文章を
検出結果のラベルを変換した文字列にすること
検出結果は
runs/detect/
の中にどんどん新しい番号が付けられて増えていくため
動的にパスを取得するスクリプトにすること

osモジュールを使用して、指定されたディレクトリ内のサブディレクトリをリストアップし、その中で最新の番号を持つディレクトリを特定できる

1. os.listdir(base_path)を使用して、指定されたディレクトリ内の全てのファイルとディレクトリのリストを取得します。
2. リスト内の要素がディレクトリであるかどうかを確認するためにos.path.isdir()を使用します。
3. predictプレフィックスを削除して数値に変換し、max()関数を使用して最大の数値を持つディレクトリを特定します。
4. os.path.join(base_path, latest_dir)を使用して、フルパスを生成します。

import os

def get_latest_directory(base_path):
    # 指定されたディレクトリ内の全てのサブディレクトリを取得
    subdirs = [d for d in os.listdir(base_path) if os.path.isdir(os.path.join(base_path, d))]
    
    # サブディレクトリ名を数値に変換し、ソートして最新のディレクトリを特定
    latest_dir = max(subdirs, key=lambda x: int(x.replace('predict', '')))
    
    return os.path.join(base_path, latest_dir)

# 使用例
base_path = 'runs/detect'
latest_dir = get_latest_directory(base_path)
print(f"Latest directory: {latest_dir}")

実行すると

File "/Users/snowpool/aw10s/inventory/utils.py", line 14, in <module> latest_dir = get_latest_directory(base_path) File "/Users/snowpool/aw10s/inventory/utils.py", line 8, in get_latest_directory latest_dir = max(subdirs, key=lambda x: int(x.replace('predict', ''))) File "/Users/snowpool/aw10s/inventory/utils.py", line 8, in <lambda> latest_dir = max(subdirs, key=lambda x: int(x.replace('predict', ''))) ValueError: invalid literal for int() with base 10: '' 

となる

原因は

ValueError: invalid literal for int() with base 10: ''

というエラーは
int()関数が空文字列を処理しようとしたときに発生

これは、predictという文字列をreplaceで削除した結果が
空文字列になる場合に起こる

例えば、predictという名前のディレクトリがある場合など

この問題を解決するために
ディレクトリ名がpredictのプレフィックスを持っているかどうかをチェックし
それ以外のディレクトリ名を無視するようにする

また、predictの後の文字列が数字であることを確認するために
追加のチェックを行う

対処として
1. predictで始まり、その後に数字が続くディレクトリのみを対象とするようにフィルタリングしています。
2. 有効なディレクトリが存在しない場合に適切なエラーメッセージを出力します。

import os

def get_latest_directory(base_path):
    # 指定されたディレクトリ内の全てのサブディレクトリを取得
    subdirs = [d for d in os.listdir(base_path) if os.path.isdir(os.path.join(base_path, d))]

    # サブディレクトリ名が 'predict' で始まり、その後に数字が続くものをフィルタリング
    predict_dirs = [d for d in subdirs if d.startswith('predict') and d[7:].isdigit()]

    if not predict_dirs:
        raise ValueError("No valid 'predict' directories found")

    # サブディレクトリ名を数値に変換し、ソートして最新のディレクトリを特定
    latest_dir = max(predict_dirs, key=lambda x: int(x[7:]))

    return os.path.join(base_path, latest_dir)

# 使用例
base_path = 'runs/detect'
latest_dir = get_latest_directory(base_path)
print(f"Latest directory: {latest_dir}")

これで実行すると

Latest directory: runs/detect/predict7

となった

次は画像ファイルパスの取得

import os

def get_latest_directory(base_path):
    # 指定されたディレクトリ内の全てのサブディレクトリを取得
    subdirs = [d for d in os.listdir(base_path) if os.path.isdir(os.path.join(base_path, d))]

    # サブディレクトリ名が 'predict' で始まり、その後に数字が続くものをフィルタリング
    predict_dirs = [d for d in subdirs if d.startswith('predict') and d[7:].isdigit()]

    if not predict_dirs:
        raise ValueError("No valid 'predict' directories found")

    # サブディレクトリ名を数値に変換し、ソートして最新のディレクトリを特定
    latest_dir = max(predict_dirs, key=lambda x: int(x[7:]))

    return os.path.join(base_path, latest_dir)

def get_image_files(directory):
    # 指定されたディレクトリ内の全ての画像ファイルのパスを取得
    image_extensions = ('.png', '.jpg', '.jpeg', '.gif', '.bmp')
    image_files = [os.path.join(directory, file) for file in os.listdir(directory) if file.lower().endswith(image_extensions)]
    return image_files

# 使用例
base_path = 'runs/detect'
latest_dir = get_latest_directory(base_path)
image_files = get_image_files(latest_dir)

print(f"Latest directory: {latest_dir}")
print("Image files:")
for image_file in image_files:
    print(image_file)

とすることで画像ファイルのパスが取得できた

Latest directory: runs/detect/predict7
Image files:
runs/detect/predict7/Baskulin1.jpg

次にこれをモジュールにして
LINEの画像パスにして送信テストする

import os
import json

def load_config(file_path):
    with open(file_path, 'r') as file:
        return json.load(file)

def get_latest_directory(base_path):
    # 指定されたディレクトリ内の全てのサブディレクトリを取得
    subdirs = [d for d in os.listdir(base_path) if os.path.isdir(os.path.join(base_path, d))]

    # サブディレクトリ名が 'predict' で始まり、その後に数字が続くものをフィルタリング
    predict_dirs = [d for d in subdirs if d.startswith('predict') and d[7:].isdigit()]

    if not predict_dirs:
        raise ValueError("No valid 'predict' directories found")

    # サブディレクトリ名を数値に変換し、ソートして最新のディレクトリを特定
    latest_dir = max(predict_dirs, key=lambda x: int(x[7:]))

    return os.path.join(base_path, latest_dir)

def get_image_files(directory):
    # 指定されたディレクトリ内の全ての画像ファイルのパスを取得
    image_extensions = ('.png', '.jpg', '.jpeg', '.gif', '.bmp')
    image_files = [os.path.join(directory, file) for file in os.listdir(directory) if file.lower().endswith(image_extensions)]
    return image_files

として

config.jsonの中の

  "image_file_path": "runs/detect/predict7/Baskulin1.jpg"

という指定を

  "image_file_path": "runs/detect"

に変更

line_order.pyの中身を

import requests
import os
from utils import load_config, get_latest_directory, get_image_files

# 設定ファイルを読み込む
config = load_config('config.json')

# 設定ファイルからトークンとディレクトリパスを取得
token = config['token']
base_path = config['image_file_path']

# 最新のpredictディレクトリを取得
latest_dir = get_latest_directory(base_path)
image_files = get_image_files(latest_dir)

url = 'https://notify-api.line.me/api/notify'
message = '通知したいテキスト'

headers = {'Authorization': f"Bearer {token}"}
params = {'message': message}

# 最新のpredictディレクトリ内の全ての画像ファイルに対してLINE Notify APIにリクエストを送信
for image_file_path in image_files:
    files = {'imageFile': open(image_file_path, 'rb')}
    
    # LINE Notify APIにリクエストを送信
    res = requests.post(url, headers=headers, params=params, files=files)

    # レスポンスを出力
    print(f"File: {image_file_path}")
    print(res.status_code)
    print(res.text)

として保存

これで

python line_order.py 

を実行すれば画像付きでLINEで送信してくれる

試しに再度新しいyolov8での推論をして
できたディレクトリを対象にするか実験する

しかし

python count_inventory_terminal.py data_bak/Baskulin1.jpg

0: 640x512 1 baskulin, 93.9ms
Speed: 2.7ms preprocess, 93.9ms inference, 2.9ms postprocess per image at shape (1, 3, 640, 512)
バスクリン: 1個

の後に

python line_order.py

を実行しても

File: runs/detect/predict7/Baskulin1.jpg
200
{"status":200,"message":"ok"}

となる

ls runs/detect
の結果も
predict		predict3	predict5	predict7
predict2	predict4	predict6

となる

どうやらyoloのコマンドで実行した時だけ
runs/predict以下に保存されるらしい

つまりカウントした後に画像を保存するプログラムを追加しないとだめ
あと、カウントした時に残り1以下になった時に
ラベルを書き出すプログラムが必要