「プログラミング」カテゴリーアーカイブ

if文から卒業!Java 8のPredicateで条件分岐をスマートに書く方法

Javaで複雑な条件分岐が増えてくると、if文がネストして読みにくくなる…という悩みを抱えたことはありませんか?
Java 8で追加された**Predicateインターフェース**を使えば、条件式をオブジェクトとして扱えるため、よりスマートで再利用可能な形にできます。

本記事では、Predicateの基本から複数条件の組み合わせ、実用的な活用例まで分かりやすく解説します。


✅ Predicateとは?

Predicate<T> はJava 8で導入された関数型インターフェースで、**「引数を1つ受け取り、booleanを返す関数」**を表します。

test()メソッドに条件式を実装することで、条件判定を行うことができます。


✅ 基本的な使い方

✔ Lambda式で判定条件を定義

ここで、age -> age >= 20 という条件式がPredicateとして表現されています。


✅ 条件を組み合わせる(and/or/negate)

Predicateは以下のような便利なメソッドを持っています。

メソッド説明使用例
and()両方trueでtrueAND条件
or()どちらかtrueでtrueOR条件
negate()条件を反転NOT条件

✔ 使用例


✅ 実用例①:従来のif文から置き換えてスマートに

❌ 従来のif文

✅ Predicateを使った場合

→ 条件式をPredicateとして切り出すことで、再利用しやすくなります。


✅ 実用例②:Listのフィルタリングに活用

stream().filter() と組み合わせるとさらに強力です。

→ 条件式が外部に切り出されることで、読みやすく拡張しやすいコードになります。


🎯 Predicateを使うメリット

項目従来のif文Predicate
可読性ネストしやすい条件名で意図が明確
再利用性条件をコピペ使い回し可能
拡張性if追加が必要and/orで柔軟に拡張

⚠ 濫用しすぎには注意!

Predicateは便利ですが、小規模な処理に無理に使うと逆に複雑化することがあります。
「条件が複数箇所で使い回せる場合」や「複雑なAND/OR条件を定義したい場合」に効果を発揮します。


✅ まとめ

項目内容
Predicateとはbooleanを返す関数型インターフェース
基本test() で条件判定
条件組み合わせand/or/negateでスマートに
実用例if文の代替・Streamのfilterで活躍
メリット可読性・再利用性UP

👉 if文が増えて可読性が下がってきたと感じたら、まずは小さな条件式からPredicate化してみましょう!

Java:Stream APIのparallelStream()で並列処理を簡単に実現する方法

🔷 はじめに

JavaのStream APIは、コレクション操作を簡潔に記述できる便利な仕組みですが、
parallelStream()を使うことで マルチスレッド処理(並列処理) を手軽に実現できます。

この記事では、parallelStream()の基本的な使い方から、注意点・パフォーマンスの最適化方法までをわかりやすく解説します。


🔷 StreamとparallelStreamの違い

種類説明特徴
stream()通常の逐次処理1スレッドで順次実行される
parallelStream()並列処理ForkJoinPoolを使って複数スレッドで分割実行される

上記のparallelStream()では、スレッドごとに要素を分割して処理するため、
出力順が異なる(順不同になる)点に注意が必要です。


🔷 並列処理の仕組み(ForkJoinPool)

parallelStream()は内部的に ForkJoinPool(フォーク・ジョイン・プール)を使用します。
デフォルトでは、Runtime.getRuntime().availableProcessors() の値(CPUコア数)に応じてスレッド数が自動決定されます。

例えば、4コアCPUの場合は最大4スレッドで同時実行されます。


🔷 実行例:リストの重い処理を並列化する

以下の例では、重い計算を伴う処理を並列実行して速度を比較します。

結果例:

逐次処理時間:5000ms
並列処理時間:1500ms

CPUコア数にもよりますが、並列処理では約3倍の高速化が期待できます。


🔷 並列処理時の注意点

注意点内容
スレッド安全性共有リソースを操作すると競合が発生する可能性あり
出力順forEach()は順序が保証されない(順序を保つにはforEachOrdered()を使用)
外部API呼び出し同時実行でAPI制限に抵触する可能性があるため注意
numbers.parallelStream()
.forEachOrdered(System.out::println); // 並列でも順序維持

🔷 並列処理の最適化テクニック

  1. 処理が軽い場合は使わない

    • 並列化のオーバーヘッドが大きく、逆に遅くなる場合があります。

  2. データ量が多い処理に限定する

    • 数千件以上の要素を扱う場合に効果的。

  3. カスタムスレッド数を指定

    • これで並列スレッド数を8に固定できます。


🔷 parallelStream()を使うべきケース

CPUバウンド処理(計算中心)
データが多い場合
スレッド安全な処理のみを行う場合

I/Oバウンド処理(ファイル操作・DBアクセス)は非推奨です。
並列化よりも非同期I/O(CompletableFutureなど)を使うほうが効率的です。


🔷 まとめ

項目内容
メリット複雑なスレッド処理を書かずに並列化できる
デメリット順序保証がない・スレッド安全性に注意
向いている処理CPU負荷の高いループ・数値計算・マッピング処理
非推奨の処理I/O、同期が必要な共有データ操作

parallelStream()は数行で並列化を実現できる強力なツールですが、
適切な場面で使うことが重要です。
CPUをフル活用して処理時間を短縮したい場面で、ぜひ活用してみてください。

Java Stream API入門:リスト操作を効率化する実用サンプル集

■ 導入:Stream APIでコードを劇的に簡潔化

Java 8以降で導入された Stream API は、リストや配列の操作を「宣言的」「関数型スタイル」で記述できる強力な仕組みです。
従来の for ループを使った処理に比べて、コード量を大幅に削減し、バグを防止 できます。

本記事では、List 操作を中心に、Stream APIの実践サンプルを多数紹介します。


■ 基本構文:Streamの流れを理解する

Streamの基本構成は以下の3ステップです。

イメージ:

データの流れ → 加工 → 出力(別のリストなどに変換)

■ サンプル①:条件でフィルタリングする

例えば「偶数だけを抽出する」処理は、以下のように書けます。

処理内容コード例説明
偶数のみ抽出filter(n -> n % 2 == 0)条件に一致する要素だけを残す

■ サンプル②:要素を変換する(map)

全ての要素を2倍にする変換も簡単です。

処理内容コード例出力例
2倍変換map(n -> n * 2)[2, 4, 6, 8]

■ サンプル③:ソート・並び替え

文字列リストをアルファベット順にソートする例です。

降順にする場合は:

処理内容メソッド説明
昇順ソートsorted()自然順序(A→Z, 1→9)
降順ソートsorted(Comparator.reverseOrder())逆順に並び替え

■ サンプル④:重複を除去する(distinct)

処理内容メソッド効果
重複削除distinct()同一要素を1つにまとめる

■ サンプル⑤:合計・平均・最大値を求める

数値リストの集計処理も簡単です。

処理メソッド結果型
合計sum()int
平均average()OptionalDouble
最大max()OptionalInt

■ サンプル⑥:複数条件の処理(filter + map)

処理順序内容
Aで始まる要素のみ抽出
すべて大文字に変換
新しいリストに収集

■ サンプル⑦:グルーピング(groupingBy)

Stream APIでは、SQLのように「グループ化」も可能です。

処理内容メソッド結果
長さごとにグループ化groupingBy(String::length){3=[Tom, Ken], 4=[John]}

■ サンプル⑧:並列処理で高速化(parallelStream)

大量データを高速処理したい場合は parallelStream() を使います。

ただし、順序が保証されない ため、結果の順序が重要な場合は通常の stream() を使用しましょう。


■ Stream APIを使うメリットまとめ

メリット内容
コードの簡潔化for文やif文のネストを削減
可読性向上処理の流れが直感的に理解できる
パフォーマンス並列処理で大量データにも対応
安全性NullPointerExceptionを防ぎやすい

■ まとめ:Stream APIを使いこなして効率化

Stream APIは一度慣れてしまえば、リスト処理を格段に楽にしてくれます。
特にJava 11以降では、ラムダ式やメソッド参照との相性も良く、業務アプリのコード品質を底上げできます。

Java初心者必見!Optionalでnullチェックを安全に行う方法【サンプル付き】

Javaで避けて通れないのが「nullチェック」。
しかし、if文を多用するとコードが読みにくくなり、思わぬNullPointerExceptionが発生することもあります。
そんな悩みを解消してくれるのが Optionalクラス です。

本記事では、Optionalを使った安全でスマートなnullチェックの方法を、サンプルコード付きで分かりやすく解説します。


💡 Optionalとは?

Optionalは、Java 8で追加されたクラスで、
nullの代わりに値の有無を明示的に扱う」ためのラッパーです。

Optionalは「値がある」か「空(empty)」かを明確に区別できるため、
if (obj != null) のような古い書き方を減らせます。


✅ よくあるnullチェックの問題例

この書き方は一見安全ですが、
複数のフィールドをネストすると次のようにネスト地獄に陥ります。

→ これをスマートに書けるのがOptionalです。


🧩 Optionalを使った安全な書き方

これだけで「nullがあれば自動的にスキップ」されます。
つまり、nullチェックをネストせずに安全に値を取り出せるのです。


🔍 Optionalの主なメソッド一覧

メソッド説明使用例
of()null禁止でOptionalを作成Optional.of("Hello")
ofNullable()null許可でOptionalを作成Optional.ofNullable(obj)
isPresent()値が存在するか判定if(opt.isPresent())
ifPresent()値がある場合に処理を実行opt.ifPresent(System.out::println)
orElse()値がない場合のデフォルト値を設定opt.orElse("default")
orElseGet()遅延生成のデフォルト値opt.orElseGet(() -> "default")
orElseThrow()値がない場合に例外を投げるopt.orElseThrow()

🧠 orElseとorElseGetの違い

比較項目orElse()orElseGet()
評価タイミング常に評価値が空のときのみ評価
パフォーマンス無駄な生成が起こる場合あり必要なときだけ生成
opt.orElse(createDefault())opt.orElseGet(() -> createDefault())

💬 ポイント:
createDefault() のような重い処理を含む場合は、orElseGet()を使う方が効率的です。


🧾 サンプルコード全体

✅ 出力結果:

名前が未設定です。

🚀 Optionalを使うメリットまとめ

メリット内容
可読性向上if文のネストを削減できる
安全性向上NullPointerExceptionのリスクを軽減
関数型スタイルmap, filter, flatMapなどと組み合わせ可能
メソッドチェーン処理の流れを1行で表現できる

⚠️ 注意点:Optionalは「すべてに使う」ものではない

  • フィールド変数に使うと逆に可読性が下がる

  • シリアライズ対象(例:エンティティクラス)には不向き

  • 「戻り値専用」として使うのが基本スタイルです。


🧭 まとめ

Optionalは「nullチェックを明示的に表現する」ための便利な仕組みです。
使い方を覚えることで、より安全で読みやすいJavaコードが書けるようになります。

🧠 Pythonで学ぶ画像認識入門:TensorFlowとKerasで手書き数字を判定する方法(5) ~複数の自作画像を一括で認識~

前回

🧠 Pythonで学ぶ画像認識入門:TensorFlowとKerasで手書き数字を判定する方法(4) ~学習済みモデルで自作画像を認識~

の記事では、学習済みモデルを使って「1枚の手書き数字画像」を判定しました。
今回はさらに発展して、フォルダ内にある複数の画像を一括で認識してみましょう。

これにより、手書きで作成した「0〜9」の数字画像をまとめてテストできるようになります。


🧩 動作環境(共通)

項目バージョン / ツール
OSWindows 11 Pro 24H2
Python3.12.6
pip24.2
エディタPowerShell / VS Code
ライブラリpandas 2.x / matplotlib 3.x / openpyxl 3.x


📁 ステップ①:フォルダ構成を準備

まず、テスト用フォルダを作成します。

各画像は 白背景 × 黒または青文字、中央寄せ、28×28ピクセル推奨です。


🧠 ステップ②:複数画像を一括認識するスクリプト

ファイル名:predict_batch.py

内容:


⚙️ ステップ③:実行方法

仮想環境を有効化して、次を実行します:


🧾 ステップ④:出力結果(例)

コンソール出力例:

グラフ表示:

  • 横一列に数字画像が並び、各画像の下にAIの判定結果が表示されます

  • 一目でどの画像をどの数字と認識したか分かります


📊 ステップ⑤:結果と考察

項目内容
処理対象フォルダ内の全画像(png/jpg)を自動スキャン
推論処理load_modelでCNNモデルを再利用し、一括predictを実施
表示形式コンソール出力+matplotlibで可視化
精度1枚ずつ推論と同等(約99%)を維持
応用例書類や帳票の一括認識、データセットの一括評価など
考察単一推論を拡張してバッチ処理化。フォルダ単位で実行できるため自動化が容易


💡 発展ポイント

テーマ内容
結果をCSV出力pandas.DataFrame(results).to_csv('result.csv', index=False)
サブフォルダ対応os.walk() を使えば階層フォルダも処理可能
推論速度UPGPU環境なら処理時間が大幅短縮
異常画像の検出サイズやフォーマットが不正な画像をスキップ処理可能

✅ まとめ

本記事では、学習済みモデルを使って複数の手書き数字画像をまとめて判定しました。
フォルダ単位で一括処理できるため、データテストやAIモデルの精度検証にも最適です。

次回は、

🧠 (6) 判定結果をCSV出力し、正解データと比較して精度を分析
として、「自作データセットの評価編」に進みます。

Java:安全な乱数生成に役立つ!SecureRandomの使いどころ

1. SecureRandomとは

SecureRandomは、**暗号論的に安全な乱数(CSPRNG:Cryptographically Secure Pseudo-Random Number Generator)**を生成するためのJavaクラスです。
java.securityパッケージに含まれ、セキュリティトークン、APIキー、暗号鍵などの生成に利用されます。

通常のRandomクラスは予測可能な乱数を生成するため、攻撃者にシードを特定される危険性があります。
対してSecureRandomはOSの暗号エンジンを利用して予測不能な乱数を生成します。


2. Randomとの違い

項目RandomSecureRandom
主な用途ゲーム・抽選・シミュレーション暗号・セキュリティ関連
再現性シード指定で再現可能予測困難・安全性重視
エントロピー源疑似乱数(数列)OSの乱数エンジン
パフォーマンス高速やや低速(安全性優先)
実装場所java.utiljava.security

3. Javaバージョン別の対応ポイント

バージョン特徴・変更点
Java 8最も広く使われる環境。SecureRandomはデフォルトで十分安全。getInstanceStrong()も使用可能(JDK実装依存)。
Java 11Base64.getUrlEncoder()などの標準エンコーダが安定。マルチスレッド環境でのSecureRandom利用も改善。
Java 17 (LTS)デフォルトの乱数アルゴリズムが強化(DRBGが推奨)。新しいSecureRandom実装が追加。
Java 21 (LTS)SecureRandomのアルゴリズム選択がより細かく制御可能に。DRBGがデフォルトで推奨パス。

💡 DRBGとは?
Java 17以降では、NIST標準(SP800-90A)に準拠したDRBG(Deterministic Random Bit Generator)が使用可能です。
これは暗号学的により強固な乱数生成手法で、今後の推奨実装となります。


4. サンプルコード:安全なトークン生成 

🧩 出力例:

安全なトークン: qZ1jJ9vCQyQJk6lK2fYvUg

5. 高度な使い方(Java 17以降対応)

✅ 強力なDRBGインスタンスを明示的に取得

💡 HexFormatはJava 17で追加された便利クラスです。
Base64よりも短い表現でログ出力に適しています。


6. よくある利用シーン

シーン使用目的推奨API
認証トークン生成セッションIDやAPIキーSecureRandom + Base64
CSRFトークンWebフォームの保護SecureRandom + HexFormat
パスワードリセットURL予測困難な一時リンク生成getInstanceStrong()
暗号鍵生成AESなどの鍵素材SecureRandom
UUID代替高強度ランダムIDSecureRandomで独自生成

7. ベストプラクティス

推奨事項理由
SecureRandomの使い回し毎回生成するとコストが高い
OS依存のソースを活用/dev/urandomなどで高品質な乱数
getInstanceStrong()を必要時のみ使用起動が遅くなるため常用は非推奨
Base64やHexFormatで可読化ログやトークンで扱いやすい
シード指定は避けるセキュリティが低下するため

8. パフォーマンス比較(目安)

操作平均速度安全性
Random.nextInt()非常に高速
SecureRandom.nextInt()中程度
SecureRandom.getInstanceStrong()やや遅い最高
SecureRandom (DRBG)中〜高最高(推奨)

9. まとめ

ポイント内容
用途暗号・認証・トークン生成に最適
バージョン対応Java 8〜21全対応
推奨実装SecureRandom または DRBG(Java 17+)
注意点シード指定・再生成の多用を避ける
一言安全性を重視する場面では必ずSecureRandomを!

🧠 コラム:SecureRandomを使うべき「具体例」

  • OAuth 2.0 認可コードの生成

  • JWTの署名鍵生成

  • Cookieのsession_id生成

  • APIトークン・CSRFトークン・暗号鍵など

「ユーザーや外部に漏れたら困る値」には必ずSecureRandom!

Java:SQL接続でつまずかないためのtry-with-resources活用法

JavaでSQL接続を扱うとき、多くの初心者が陥るのが「リソースの解放忘れ」「例外処理の煩雑さ」です。
特に Connection, PreparedStatement, ResultSet の3つは明示的に close() しないと、メモリリークや接続枯渇の原因になります。

この記事では、そんな問題をtry-with-resources構文でスマートに解決する方法を紹介します。


🧱 try-with-resourcesとは?

Java 7以降で導入された構文で、AutoCloseable インターフェースを実装したオブジェクトを
自動的にクローズしてくれる仕組みです。

✅ 従来のコード例(Java 6以前)


👉 冗長で、finally ブロックがネストしやすく、例外の見落としが発生しやすいのが難点です。

🚀 try-with-resourcesを使った改良版


✨ メリットまとめ
項目従来の書き方try-with-resources
リソース解放明示的にclose()が必要自動でcloseされる
コード量冗長スッキリ
例外の安全性finallyで記述ミスの恐れ例外を安全に補足
可読性低い高い

🧠 複数リソースを扱うときのポイント

try(...) の中で複数のリソースを「セミコロン ;」で区切って宣言できます。


順序は重要

最後に開いたリソース (ResultSet) から順に自動クローズされます(LIFO順)。


⚙️ try-with-resourcesとカスタムクラス

自作クラスでも AutoCloseable を実装すれば、
try-with-resources構文で安全に自動クローズが可能です。


出力結果:
処理中...
リソースを解放しました

⚠️ 注意点:例外の隠蔽に注意

もし try 内と close() 内の両方で例外が発生した場合、
try 内の例外が優先され、close() の例外は「抑制された例外」として記録されます。


🔍 まとめ

ポイント内容
構文try(リソース宣言){ ... }
バージョンJava 7以降
対応型AutoCloseableを実装する全クラス
主な利点コード簡略化・例外安全性・リソースリーク防止

💬 おわりに

try-with-resources は見た目以上に強力です。
「リソース管理を明示的に書かない」だけで、コードの信頼性と保守性が大幅に向上します。

特にSQL接続まわりでは、この構文を使わない理由がないほどの必須テクニックです。
今後のJava開発では「標準の書き方」として身につけておきましょう。

CSSとHTMLだけで作る立体的カードUI(Shadow DOM対応)

JavaScriptなしで、transform / perspective / layered shadowsCSSカスタムプロパティ だけで

“パッ”と目を引く3Dカードを作成してみましょう。

さらに Shadow DOM 内でも同じ見た目を再現できるよう、::part() と変数で拡張可能にします。


ゴール(できあがりイメージ)

  • マウスホバーでわずかに傾く3D表現

  • 斜めに流れるハイライト(きらめき)

  • ライト/ダークどちらでも映える配色

  • prefers-reduced-motion でアニメ控えめ

  • Shadow DOM対応::part() と CSS変数で外部からのテーマ変更OK

デモ:CSSとHTMLだけで作る3DカードUI

💡 マウスを乗せるとカードがわずかに傾き、立体的な効果が確認できます。


最小HTML(ライトDOM版) 

コアCSS(ライトDOM版) 


Shadow DOM に対応させる考え方

ポイントは 「パーツを切り出す」「CSS変数でテーマ化」
外側(ライトDOM)から Shadow DOM 内を直接スタイルできないため、コンポーネント作者が part を付与し、利用者は ::part() で装飾色や半径は CSS変数で調整します。

Web Component 側(作者向け:影DOM内のテンプレ)

※ここでは概念を示すための HTMLスケッチ です。実際の ShadowRoot 作成は JS が必要ですが、スタイル設計の指針としてご覧ください。

利用者側(外部)からのテーマ上書き例 

まとめ

  • 作者は Shadow DOM 内で CSS変数part名を定義

  • 利用者ホストへ変数指定し、必要なら ::part() でピンポイント調整


デザインバリエーション(クラス追加だけ)


アクセシビリティと実用Tips

  • ボタン/リンクのヒット領域は最低44×44pxを意識(paddingで確保)

  • prefers-reduced-motion に配慮(すでに対応)

  • コントラストoklchcolor-mix()で暗所・明所どちらも読みやすく

  • 画像のalt を適切に

  • フォールバック:古い環境では oklch が未対応 → 代替色を上書き可能に


よく使うCSSカスタムプロパティ(外から上書きOK)

変数名役割
--card-bg背景色#fff / #111
--card-fg文字色#111 / #eee
--card-accentCTAなどの強調色oklch(0.78 0.17 30)
--card-radius角丸12px / 20px
--card-shadow-1影レイヤ(近)0 1px 2px rgba(0,0,0,.2)
--card-shadow-2影レイヤ(遠)0 8px 24px rgba(0,0,0,.12)
--card-border境界線1px solid rgba(0,0,0,.06)
--card-tilt傾き(通常)rotateX(5deg) rotateY(-6deg)
--card-tilt-hover傾き(ホバー)rotateX(6.5deg) rotateY(-10deg)
--card-glossハイライトlinear-gradient(120deg, transparent 30%, rgba(255,255,255,.4) 45%, transparent 60%)
--card-gloss-sizeハイライトサイズ200% 200%

トラブルシュート

  • 立体感が弱い--card-tilt と影(--card-shadow-2)を強める

  • グロスが強すぎる--card-gloss の不透明度を上げる(=白を薄く)

  • 画面酔いprefers-reduced-motion 環境で確認、もしくはカードに .is-outline を付与

  • Shadow DOM で色が変わらない → 変数は ホスト(custom element)側に定義しているか確認


まとめ

項目ポイント
3D表現transformとperspectiveで奥行きを演出
輝き::beforeのグラデとbackground-positionで流し込み
配色oklchとcolor-mixでライト/ダーク両対応
アクセシビリティprefers-reduced-motionと十分なヒット領域
Shadow DOM作者はpart公開&変数化/利用者は::part()と変数上書き
拡張クラス追加でelevated/glass/outlineを切替

JSいらず!HTMLだけでポップアップを出せる「popover」属性がすごい

これまで「ポップアップ」や「モーダルウィンドウ」を作るには、
JavaScriptやCSSトリックを駆使するのが当たり前でした。

ところが最近、**HTMLだけでポップアップを表示できる新属性「popover」**が登場!
これが想像以上にシンプルで、しかも見た目も自然なんです。

この記事では、「popover」属性の基本的な使い方から応用例までまとめています。


🚀 popover属性とは?

popover属性は、HTMLの要素に「ちょっとした吹き出し」や「軽いモーダル」を表示するための新仕様です。
JavaScriptなしで開閉制御でき、ボタンやリンクに紐づけて簡単に使えます。

対応ブラウザ

  • ✅ Chrome 114以降

  • ✅ Edge 114以降

  • ✅ Safari 17以降

  • ⚠️ Firefox(現時点では開発中)

※2025年現在、多くのモダンブラウザでサポートが進んでいます。


🧱 基本の使い方

✅ 最小構成の例 


<表示例>

💬 ポイント解説

  • popover 属性を付与した要素が、ポップアップ対象になります。

  • popovertarget 属性で、どの要素を表示するか指定します。

  • ボタンをクリックするだけで自動的に開閉制御してくれます。


🎨 スタイルを整える

デフォルトのままだと少し味気ないので、CSSで整えましょう。


これで、軽いツールチップやメニュー風の見た目にできます。

背景を白系にすれば、Webアプリ風のモーダルにも。


⚙️ 応用:自動で閉じる・メニュー風表示 

popovertargetaction="toggle" を使うと、クリックごとに開閉を切り替えられます。
ナビゲーションメニューやヘルプボックスなどにも応用可能です。

<表示例>


🧠 裏側の仕組み

HTMLの「popover」属性は、ブラウザ側で開閉制御を自動的に処理します。
内部的には :popover-open という擬似クラスが追加され、
CSSで開閉状態を検知することもできます。


この仕組みにより、JSでイベントを監視せずとも

**「開いたときだけアニメーション」**などを実現できます。


💻 実用例:通知メッセージ


JavaScript不要で、ユーザーに小さなメッセージを伝えることが可能です。

フォーム送信後の完了メッセージなどにもぴったり。


⚠️ 注意点

  • 古いブラウザでは未対応なので、必要に応じて<dialog>タグやJSフォールバックを検討。

  • 開く方向は自動制御されるため、細かい位置調整が難しい場合があります。

  • 長文や複雑なレイアウトには不向き(軽量ポップアップ用途がベスト)。


🌟 まとめ

特徴内容
JavaScript不要HTMLだけで完結
見た目自由CSSで簡単カスタマイズ
軽量ページ読み込みが早い
一部ブラウザ注意Firefoxは実装中

🔮 今後の展望

「popover」属性はまだ新しい技術ですが、
“JavaScriptレスなUI” を目指すHTML進化の象徴です。

今後は、ツールチップ・通知・設定メニューなど、
より多くのシーンで採用が進むと期待されます。

🧠 Pythonで学ぶ画像認識入門:TensorFlowとKerasで手書き数字を判定する方法(4) ~学習済みモデルで自作画像を認識~

前回の

🧠 Pythonで学ぶ画像認識入門:TensorFlowとKerasで手書き数字を判定する方法(3) ~CNNによる高精度モデル編~

までで、MNISTデータセットを使い高精度なCNNモデルを作成しました。
今回はその学習済みモデルを再利用し、自分で描いた手書き数字画像を実際に判定してみましょう。


ステップ①:学習済みモデルの保存

前回での学習コードに以下を追加して、モデルを保存しておきます。


これで C:\python_env\mnist_cnn_model.h5 が生成されます。


ステップ②:自作画像を準備する

1️⃣ 白背景に黒文字で「0〜9」の数字を描いた画像を用意
2️⃣ 画像サイズを 28×28ピクセル にリサイズ
3️⃣ ファイル形式は .png または .jpg でOK

(例)

C:\python_env\my_digit.png

※手書きペイントツールで描いてもOK。
できるだけ文字を中央に配置し、背景は白が理想です。


ステップ③:推論スクリプトを作成

ファイル名:

predict_my_digit.py

内容:


ステップ④:実行

仮想環境を有効化して、次のコマンドを実行:


ステップ⑤:結果と考察

項目内容
予測結果AIが自作の手書き数字を正しく認識し、予測結果が画面に表示される
処理時間数百ミリ秒程度で即時に判定が完了
注意点白背景×黒文字の前提で学習しているため、背景と文字が逆の場合は反転処理を削除
応用例手書き書類の数字抽出、郵便番号や伝票番号の自動読み取りなどに応用可能
考察CNNモデルにより自作データでも高い精度を維持。前処理(反転・正規化)が認識精度に大きく影響

💡 ワンポイント

もし背景が黒で文字が白の場合は、
次の行を削除してください:


✅ まとめ

これで「自分の描いた手書き数字」をAIが正しく認識できるようになりました。
この流れを応用すれば、より複雑な画像分類(例えば「猫と犬」や「手書き文字分類」)にも発展できます。