スマート農業IT教育



📷 画像処理・画像分析 in スマート農業(週単位教材)

🔹 フェーズ1:画像処理の基礎(OpenCV中心)【Week 1〜8】

🔹 フェーズ2:ディープラーニングによる画像認識【Week 9〜16】

🔹 フェーズ3:農業現場応用プロジェクト制作【Week 17〜24】


🧪 フェーズ1:画像処理基礎(OpenCV中心)【Week 1〜8】

タイトル内容概要ノートブック例
Week 1画像ファイルの読み込みと表示OpenCV入門、画像のRGB/BGR変換、チャンネル操作week01_opencv_intro.ipynb
Week 2基本的な画像処理グレースケール変換、ぼかし(平滑化)、閾値処理week02_opencv_processing.ipynb
Week 3輪郭検出と形状解析Canny、輪郭抽出、面積・外接矩形の計算week03_contour_analysis.ipynb
Week 4ヒストグラム解析明るさ/色の分布、ヒストグラム平坦化week04_histogram_analysis.ipynb
Week 5幾何変換リサイズ、回転、アフィン・射影変換week05_geometry_transforms.ipynb
Week 6マスキングと領域抽出ROI抽出、条件付き抽出(色・閾値)week06_masking_roi.ipynb
Week 7画像合成と透過処理加重合成、透明背景合成(アルファチャンネル)week07_compositing.ipynb
Week 8応用演習①:葉面積の測定例:作物の葉を二値化→面積計算week08_leaf_area_calc.ipynb

🧠 フェーズ2:ディープラーニングによる画像分析【Week 9〜16】

タイトル内容概要ノートブック例
Week 9CNN基礎①Convolutionの仕組み、MaxPoolingなどweek09_cnn_intro.ipynb
Week 10CNN基礎②kerasによるシンプルなCNN構築(分類)week10_cnn_build.ipynb
Week 11データ拡張と前処理回転・反転・拡張による学習改善week11_data_aug.ipynb
Week 12転移学習(ResNet等)学習済みモデルの応用とfine-tuningweek12_transfer_learning.ipynb
Week 13精度評価と混同行列精度/再現率/F1・Confusion Matrixの表示week13_model_eval.ipynb
Week 14物体検出①:YOLOv5入門基本構造と使い方week14_yolo_intro.ipynb
Week 15物体検出②:農業応用害虫・病斑・果実検出などweek15_yolo_agri.ipynb
Week 16応用演習②:病気画像分類農研機構データを使った病気識別week16_disease_classify.ipynb

🌾 フェーズ3:農業現場応用プロジェクト制作【Week 17〜24】

💡 プロジェクトテーマ例(応用)


各週毎の学習内容


week01

以下が、画像処理の入門として構成されたノートブック week01_opencv_intro.ipynb の内容です。
この週では、OpenCV を用いた画像の基本操作(読み込み・表示・加工) を通して、農業画像処理への第一歩を学びます。

🧪 week01_opencv_intro.ipynb: OpenCVによる画像処理入門

# week01_opencv_intro.ipynb:OpenCV 基本操作

import cv2
import matplotlib.pyplot as plt
import numpy as np

# Google Colab環境用: サンプル画像のアップロード
from google.colab import files
uploaded = files.upload()

# 画像読み込み
image_path = list(uploaded.keys())[0]  # 最初にアップロードされたファイル
img = cv2.imread(image_path)

# OpenCV は BGR → RGB に変換して表示する必要あり
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 画像表示
plt.figure(figsize=(8, 6))
plt.imshow(img_rgb)
plt.title("📷 入力画像")
plt.axis("off")
plt.show()

# --- 基本操作 ---
# グレースケール変換
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# リサイズ
resized = cv2.resize(img_rgb, (200, 200))

# 回転(中心回転)
(h, w) = img.shape[:2]
center = (w // 2, h // 2)
matrix = cv2.getRotationMatrix2D(center, 45, 1.0)  # 45度回転
rotated = cv2.warpAffine(img_rgb, matrix, (w, h))

# 画像の保存(例)
cv2.imwrite("rotated_image.jpg", rotated)

# --- 表示まとめ ---
fig, ax = plt.subplots(1, 3, figsize=(15, 4))
ax[0].imshow(gray, cmap='gray')
ax[0].set_title("Grayscale")

ax[1].imshow(resized)
ax[1].set_title("Resized")

ax[2].imshow(rotated)
ax[2].set_title("Rotated (45°)")

for a in ax:
    a.axis("off")

plt.tight_layout()
plt.show()

✅ 学べることまとめ

機能説明
cv2.imread()画像ファイルの読み込み
cv2.cvtColor()カラーモード変換(BGR→RGB, グレースケールなど)
cv2.resize()任意サイズへの画像リサイズ
cv2.getRotationMatrix2D() + warpAffine()画像の回転
cv2.imwrite()加工画像の保存

💡 発展課題


week02

以下は、OpenCV を使った画像の前処理テクニックを扱うノートブック week02_opencv_processing.ipynb の内容です。 この週では、農業画像処理の基礎的なフィルタリング・しきい値処理・輪郭抽出 など、次週以降の分析や分類処理に繋がる重要な前処理手法を学びます。

🧪 week02_opencv_processing.ipynb: OpenCVによる画像前処理

# week02_opencv_processing.ipynb:OpenCV 前処理編

import cv2
import numpy as np
import matplotlib.pyplot as plt
from google.colab import files

# ファイルアップロード
uploaded = files.upload()
image_path = list(uploaded.keys())[0]
img = cv2.imread(image_path)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# グレースケール変換
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 1. 平滑化(ぼかし処理)
blur = cv2.GaussianBlur(gray, (5, 5), 0)

# 2. しきい値処理(二値化)
_, binary = cv2.threshold(blur, 100, 255, cv2.THRESH_BINARY)

# 3. Canny エッジ検出
edges = cv2.Canny(blur, 50, 150)

# 4. 輪郭検出
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contour_img = img_rgb.copy()
cv2.drawContours(contour_img, contours, -1, (255, 0, 0), 2)

# 画像表示まとめ
titles = ["グレースケール", "ぼかし処理", "二値化", "エッジ検出", "輪郭抽出"]
images = [gray, blur, binary, edges, contour_img]

plt.figure(figsize=(15, 8))
for i in range(5):
    plt.subplot(2, 3, i+1)
    if i < 4:
        plt.imshow(images[i], cmap='gray')
    else:
        plt.imshow(images[i])
    plt.title(titles[i])
    plt.axis("off")
plt.tight_layout()
plt.show()

✅ 学べる処理と目的

処理手法内容・活用例
グレースケール変換処理の前段階として色情報を減らす
ぼかし(平滑化)ノイズ除去。GaussianBlur を使用
二値化処理背景と対象を分離(例:葉 vs 背景)
エッジ検出境界線の検出。物体の形状を把握
輪郭抽出葉・果実などの外形を捉える際に使用

🌱 農業応用の例

🧪 発展課題


week03

こちらが、輪郭や領域の定量的な解析にフォーカスしたノートブック week03_contour_analysis.ipynb の内容です。
この週では、OpenCVで得た輪郭に対する面積・周囲長・アスペクト比・ヒストグラム などの特徴量抽出を行い、画像からの定量データ取得を体験します。

🧪 week03_contour_analysis.ipynb: 輪郭と特徴量の抽出・分析

# week03_contour_analysis.ipynb:輪郭解析と特徴量抽出

import cv2
import numpy as np
import matplotlib.pyplot as plt
from google.colab import files

# ファイルアップロード
uploaded = files.upload()
image_path = list(uploaded.keys())[0]
img = cv2.imread(image_path)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 前処理:ぼかし + 二値化
blur = cv2.GaussianBlur(gray, (5, 5), 0)
_, binary = cv2.threshold(blur, 100, 255, cv2.THRESH_BINARY)

# 輪郭抽出
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 輪郭ごとの特徴量抽出
features = []
annotated_img = img_rgb.copy()

for i, cnt in enumerate(contours):
    area = cv2.contourArea(cnt)
    perimeter = cv2.arcLength(cnt, True)
    
    # バウンディングボックス
    x, y, w, h = cv2.boundingRect(cnt)
    aspect_ratio = float(w) / h
    
    # ラベル描画
    cv2.rectangle(annotated_img, (x, y), (x+w, y+h), (0, 255, 0), 2)
    cv2.putText(annotated_img, f"#{i+1}", (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)

    features.append({
        "ID": i+1,
        "Area": area,
        "Perimeter": perimeter,
        "AspectRatio": aspect_ratio,
        "BoundingBox": (x, y, w, h)
    })

# 結果表示
plt.figure(figsize=(8, 6))
plt.imshow(annotated_img)
plt.title("輪郭と特徴量の可視化")
plt.axis("off")
plt.show()

# 特徴量テーブル表示
import pandas as pd
df_features = pd.DataFrame(features)
df_features

✅ 学べること

機能・処理説明
cv2.contourArea()面積の計算
cv2.arcLength()周囲長の計算
cv2.boundingRect()バウンディングボックスとアスペクト比
cv2.putText()輪郭にIDを表示する

🌱 農業応用の例

🧪 発展課題


week02

以下は、色解析とヒストグラムを中心に学ぶノートブック week04_histogram_analysis.ipynb の内容です。
この週では、画像内の色情報の可視化・ヒストグラムの解析・しきい値処理や色抽出の応用 を学び、葉の健康状態や作物の熟度判定などへの応用の基礎を固めます。

🧪 week04_histogram_analysis.ipynb: 色解析とヒストグラム分析

# week04_histogram_analysis.ipynb:色ヒストグラムとマスク処理

import cv2
import numpy as np
import matplotlib.pyplot as plt
from google.colab import files

# 画像アップロード
uploaded = files.upload()
image_path = list(uploaded.keys())[0]
img = cv2.imread(image_path)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# --- 色ヒストグラムの表示(RGB別) ---
colors = ('r', 'g', 'b')
plt.figure(figsize=(10, 4))
for i, col in enumerate(colors):
    hist = cv2.calcHist([img_rgb], [i], None, [256], [0, 256])
    plt.plot(hist, color=col)
    plt.xlim([0, 256])
plt.title("RGBヒストグラム")
plt.xlabel("画素値")
plt.ylabel("出現頻度")
plt.grid(True)
plt.show()

# --- HSV変換と色抽出(例:緑) ---
hsv = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HSV)

# 緑の範囲を指定
lower_green = np.array([35, 40, 40])
upper_green = np.array([85, 255, 255])

# マスク作成と適用
mask = cv2.inRange(hsv, lower_green, upper_green)
result = cv2.bitwise_and(img_rgb, img_rgb, mask=mask)

# 結果表示
fig, ax = plt.subplots(1, 3, figsize=(16, 5))
ax[0].imshow(img_rgb)
ax[0].set_title("元画像")
ax[1].imshow(mask, cmap='gray')
ax[1].set_title("緑色マスク")
ax[2].imshow(result)
ax[2].set_title("抽出結果(緑)")
for a in ax:
    a.axis("off")
plt.tight_layout()
plt.show()

✅ 学べる処理

処理名説明
cv2.calcHist()色ヒストグラムの算出(R, G, B)
cv2.cvtColor()RGB → HSV 変換(色抽出しやすい)
cv2.inRange()指定色の範囲をマスクとして抽出
cv2.bitwise_and()マスクに基づく色領域の抽出

🌾 農業応用アイデア

🧪 発展課題


week05

以下は、画像の幾何変換やリサイズ・回転・切り出しを扱うノートブック week05_geometry_transforms.ipynb の内容です。
この週では、画像前処理の一環としての座標操作やアフィン変換の基礎 を身につけ、データ拡張や部分領域の抽出(ROI)などの応用を可能にします。

🧪 week05_geometry_transforms.ipynb: 幾何変換とROI抽出

# week05_geometry_transforms.ipynb:幾何変換・リサイズ・切り出し・回転

import cv2
import numpy as np
import matplotlib.pyplot as plt
from google.colab import files

# 画像アップロード
uploaded = files.upload()
image_path = list(uploaded.keys())[0]
img = cv2.imread(image_path)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# --- 1. リサイズ ---
resized = cv2.resize(img_rgb, (300, 300))

# --- 2. 切り出し(ROI)---
h, w = img_rgb.shape[:2]
roi = img_rgb[h//4:h//4*3, w//4:w//4*3]

# --- 3. 回転(中心回転) ---
center = (w // 2, h // 2)
matrix = cv2.getRotationMatrix2D(center, angle=45, scale=1.0)
rotated = cv2.warpAffine(img_rgb, matrix, (w, h))

# --- 4. アフィン変換 ---
pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
pts2 = np.float32([[60, 70], [220, 50], [70, 250]])
M_affine = cv2.getAffineTransform(pts1, pts2)
affine = cv2.warpAffine(img_rgb, M_affine, (w, h))

# --- 表示 ---
titles = ['Original', 'Resized', 'ROI', 'Rotated', 'Affine Transform']
images = [img_rgb, resized, roi, rotated, affine]

plt.figure(figsize=(16, 8))
for i in range(5):
    plt.subplot(2, 3, i+1)
    plt.imshow(images[i])
    plt.title(titles[i])
    plt.axis('off')
plt.tight_layout()
plt.show()

✅ 学べる処理と応用

処理内容使用関数応用例
リサイズcv2.resize学習用データの統一
ROI抽出配列スライス葉や果実の一部だけを分析
回転getRotationMatrix2D, warpAffineデータ拡張、角度補正
アフィン変換getAffineTransform, warpAffine視点補正、形状変形

🌱 農業応用の例

🧪 発展課題


week06

こちらが、画像内の特定領域(ROI)をマスク処理によって抽出・分析するためのノートブック week06_masking_roi.ipynb の内容です。
この週では、色抽出+輪郭+マスクの組み合わせにより、「分析対象を限定して処理する」実践力を養います。

🧪 week06_masking_roi.ipynb: マスクによるROI抽出と解析

# week06_masking_roi.ipynb:色と輪郭を用いたROIマスク抽出

import cv2
import numpy as np
import matplotlib.pyplot as plt
from google.colab import files

# 画像アップロード
uploaded = files.upload()
image_path = list(uploaded.keys())[0]
img = cv2.imread(image_path)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
hsv = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HSV)

# --- 緑色の範囲をマスク ---
lower_green = np.array([35, 40, 40])
upper_green = np.array([85, 255, 255])
mask = cv2.inRange(hsv, lower_green, upper_green)

# --- 輪郭抽出 ---
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# --- 最大輪郭を抽出(最も大きな葉など) ---
max_contour = max(contours, key=cv2.contourArea)
roi_mask = np.zeros_like(mask)
cv2.drawContours(roi_mask, [max_contour], -1, 255, -1)  # 塗りつぶし

# --- マスクを用いてROI画像を抽出 ---
roi_extracted = cv2.bitwise_and(img_rgb, img_rgb, mask=roi_mask)

# --- ヒストグラム(ROI部分のみ) ---
masked_pixels = cv2.bitwise_and(hsv, hsv, mask=roi_mask)
hist_hue = cv2.calcHist([masked_pixels], [0], roi_mask, [180], [0, 180])

plt.figure(figsize=(14, 6))
plt.subplot(1, 3, 1)
plt.imshow(img_rgb)
plt.title("元画像")
plt.axis("off")

plt.subplot(1, 3, 2)
plt.imshow(roi_extracted)
plt.title("ROI抽出(最大葉)")
plt.axis("off")

plt.subplot(1, 3, 3)
plt.plot(hist_hue, color='g')
plt.title("ROI部分の色相ヒストグラム")
plt.xlabel("Hue (色相)")
plt.ylabel("出現頻度")
plt.grid(True)

plt.tight_layout()
plt.show()

✅ 学べる処理と要点

処理内容説明
色範囲指定マスク緑色など特定範囲をマスクで抽出
最大輪郭の抽出面積最大の葉や果実の選別
マスク付きbitwise_and処理ROIのみ可視化・処理対象とする
ROI領域のヒストグラム解析ROI限定の色情報・形状情報取得

🌾 農業応用の例

🧪 発展課題


week07

こちらが、画像から抽出した色・形状・面積などの特徴量を統合して分析するためのノートブック week07_compositing.ipynb の内容です。
この週では、ROI単位で得られた情報を 構造化データとして整形・比較 することで、分類や時系列分析への土台を作ります。

🧪 week07_compositing.ipynb: 特徴量の統合と構造化

# week07_compositing.ipynb:色・形状の統合特徴量をCSVとして抽出

import cv2
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from google.colab import files

# 画像アップロード(複数対応)
uploaded = files.upload()
data = []

for filename in uploaded.keys():
    img = cv2.imread(filename)
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    hsv = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HSV)
    
    # 色マスク(緑)
    lower_green = np.array([35, 40, 40])
    upper_green = np.array([85, 255, 255])
    mask = cv2.inRange(hsv, lower_green, upper_green)
    
    # 輪郭検出
    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    for cnt in contours:
        area = cv2.contourArea(cnt)
        if area < 100:  # 小さいノイズ除去
            continue
        
        # 輪郭マスク
        roi_mask = np.zeros_like(mask)
        cv2.drawContours(roi_mask, [cnt], -1, 255, -1)
        
        # ROI領域のHSV取得
        roi_pixels = cv2.bitwise_and(hsv, hsv, mask=roi_mask)
        
        # 平均HSV値
        mean_val = cv2.mean(roi_pixels, mask=roi_mask)
        mean_h, mean_s, mean_v = mean_val[:3]
        
        # 輪郭の外接矩形
        x, y, w, h = cv2.boundingRect(cnt)
        aspect_ratio = w / h
        
        # データに追加
        data.append({
            'filename': filename,
            'area': area,
            'mean_h': mean_h,
            'mean_s': mean_s,
            'mean_v': mean_v,
            'aspect_ratio': aspect_ratio
        })

# --- DataFrame化してCSV保存 ---
df = pd.DataFrame(data)
df.to_csv("roi_features.csv", index=False)
files.download("roi_features.csv")

# --- 表示 ---
print("抽出された特徴量(上位5件):")
print(df.head())

# --- 可視化(面積 vs 色相) ---
plt.figure(figsize=(8, 6))
plt.scatter(df['area'], df['mean_h'], c=df['mean_h'], cmap='hsv', s=30)
plt.xlabel("面積")
plt.ylabel("平均色相 (Hue)")
plt.title("面積 vs 色相")
plt.grid(True)
plt.colorbar(label='Hue')
plt.show()

✅ この週のゴール

要素内容
色特徴平均 Hue / Saturation / Value
形状特徴面積・アスペクト比(縦横比)
多画像対応複数ファイルをまとめて処理
CSV化構造化データとして出力・学習準備
散布図分析異常検知やクラスタリングの布石に

🌾 農業応用の例

🧪 発展課題


8

week0

こちらが、画像から葉の面積をより高精度に算出するためのノートブック week08_leaf_area_calc.ipynb の内容です。
この週では、実寸換算・輪郭面積の厳密取得を通じて、農業現場で重要な「葉面積の定量評価」を可能にします。

🧪 week08_leaf_area_calc.ipynb: 葉の面積計測と実寸換算

# week08_leaf_area_calc.ipynb:葉面積をピクセル単位&cm²単位で測定

import cv2
import numpy as np
import matplotlib.pyplot as plt
from google.colab import files

# --- 画像アップロード ---
uploaded = files.upload()
image_path = list(uploaded.keys())[0]
img = cv2.imread(image_path)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
hsv = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HSV)

# --- 緑色マスクの作成 ---
lower_green = np.array([35, 40, 40])
upper_green = np.array([85, 255, 255])
mask = cv2.inRange(hsv, lower_green, upper_green)

# --- 輪郭抽出 ---
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# --- 面積測定(最大輪郭) ---
leaf_contour = max(contours, key=cv2.contourArea)
area_px = cv2.contourArea(leaf_contour)

# --- 実寸換算:キャリブレーション(仮に1px = 0.05cmとする) ---
px_to_cm = 0.05  # 1ピクセル = 0.05cm
area_cm2 = (area_px * (px_to_cm ** 2))

# --- 結果表示 ---
img_contour = img_rgb.copy()
cv2.drawContours(img_contour, [leaf_contour], -1, (255, 0, 0), 2)

plt.figure(figsize=(8, 6))
plt.imshow(img_contour)
plt.title(f"面積: {area_px:.1f} px² / 約 {area_cm2:.2f} cm²")
plt.axis("off")
plt.show()

# --- 数値出力 ---
print(f"ピクセル面積: {area_px:.1f} px²")
print(f"実寸換算面積: {area_cm2:.2f} cm² (換算係数: {px_to_cm}cm/pixel)")

✅ この週のポイント

内容説明
色マスク+輪郭抽出葉部分を特定し、最大輪郭を抽出
輪郭面積(ピクセル)cv2.contourArea() を使用
実寸換算キャリブレーション係数に基づく
視覚化と定量評価作物ごとの成長・健康評価へ応用可

🌱 農業での活用場面

🧪 発展課題


week09

こちらが、画像分類の基礎として CNN(畳み込みニューラルネットワーク) を使ったモデル構築の入門ノートブック
week09_cnn_intro.ipynb の内容です。
この週では、葉の画像を使って「病気 or 健康」などの 2クラス分類タスクに取り組み、画像→判定のパイプライン構築を体験します。

🤖 week09_cnn_intro.ipynb: CNNによる画像分類の入門

# week09_cnn_intro.ipynb:KerasでCNNモデルを構築し、葉画像を分類

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras import layers, models
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# --- Google Drive連携(データフォルダを置く) ---
from google.colab import drive
drive.mount('/content/drive')

# --- データの準備 ---
# フォルダ構成:
# /content/drive/MyDrive/datasets/leaf_images/
# ├── healthy/
# └── diseased/

data_dir = '/content/drive/MyDrive/datasets/leaf_images/'

# --- データ拡張と前処理 ---
datagen = ImageDataGenerator(
    rescale=1./255,
    validation_split=0.2,
    rotation_range=20,
    zoom_range=0.2,
    horizontal_flip=True
)

train_data = datagen.flow_from_directory(
    data_dir,
    target_size=(128, 128),
    batch_size=32,
    class_mode='binary',
    subset='training'
)

val_data = datagen.flow_from_directory(
    data_dir,
    target_size=(128, 128),
    batch_size=32,
    class_mode='binary',
    subset='validation'
)

# --- CNNモデル構築 ---
model = models.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(128, 128, 3)),
    layers.MaxPooling2D(2, 2),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D(2, 2),
    layers.Conv2D(128, (3, 3), activation='relu'),
    layers.MaxPooling2D(2, 2),
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dense(1, activation='sigmoid')
])

# --- コンパイルと学習 ---
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
history = model.fit(train_data, epochs=10, validation_data=val_data)

# --- 学習曲線の可視化 ---
plt.plot(history.history['accuracy'], label='Train Accuracy')
plt.plot(history.history['val_accuracy'], label='Val Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.title('CNN Accuracy')
plt.show()

✅ この週で学べること

項目内容
CNNの構造畳み込み → プーリング → Flatten → 全結合
データ前処理正規化・データ拡張(回転・ズーム)
分類の実行健康葉 vs 病葉など
モデル評価精度と損失の可視化

🌾 農業応用例

🧪 発展課題


week10

こちらが、画像分類モデルを本格構築・保存し、今後の応用(ダッシュボードやアプリ連携)に備えるノートブック
week10_cnn_build.ipynb の内容です。
この週では、モデルの再構成・保存・読み込みまでの流れを体験し、実運用につながる技術を身につけます。

🤖 week10_cnn_build.ipynb: CNNモデルの本格構築・保存・評価

# week10_cnn_build.ipynb:CNN構築・保存・テスト予測まで

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras import layers, models
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing import image
import os

# --- Google Drive マウント(データとモデル保存用) ---
from google.colab import drive
drive.mount('/content/drive')

# --- ディレクトリ設定 ---
data_dir = '/content/drive/MyDrive/datasets/leaf_images/'  # healthy / diseased のサブフォルダを持つ
model_save_path = '/content/drive/MyDrive/models/leaf_cnn_model.h5'

# --- データ前処理 ---
datagen = ImageDataGenerator(
    rescale=1./255,
    validation_split=0.2
)

train_data = datagen.flow_from_directory(
    data_dir,
    target_size=(128, 128),
    batch_size=32,
    class_mode='binary',
    subset='training'
)

val_data = datagen.flow_from_directory(
    data_dir,
    target_size=(128, 128),
    batch_size=32,
    class_mode='binary',
    subset='validation'
)

# --- CNN構築 ---
model = models.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(128, 128, 3)),
    layers.MaxPooling2D(2, 2),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D(2, 2),
    layers.Conv2D(128, (3, 3), activation='relu'),
    layers.MaxPooling2D(2, 2),
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dropout(0.3),
    layers.Dense(1, activation='sigmoid')
])

# --- コンパイル・学習 ---
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
history = model.fit(train_data, epochs=10, validation_data=val_data)

# --- モデル保存 ---
model.save(model_save_path)
print(f"✅ モデル保存完了:{model_save_path}")

# --- 学習曲線表示 ---
plt.plot(history.history['accuracy'], label='Train Acc')
plt.plot(history.history['val_accuracy'], label='Val Acc')
plt.legend()
plt.title('CNN Accuracy')
plt.show()

🧪 モデルの評価と推論テスト(任意)

# --- 保存モデル読み込み ---
model = load_model(model_save_path)

# --- 単一画像による予測 ---
test_img_path = '/content/drive/MyDrive/test_leaf.jpg'
img = image.load_img(test_img_path, target_size=(128, 128))
img_array = image.img_to_array(img) / 255.0
img_array = np.expand_dims(img_array, axis=0)

prediction = model.predict(img_array)[0][0]
label = "Diseased" if prediction > 0.5 else "Healthy"

plt.imshow(img)
plt.title(f"予測: {label}(スコア: {prediction:.2f})")
plt.axis('off')
plt.show()

✅ この週のポイント

項目内容
CNN構成の強化Dropout追加などで汎化能力アップ
モデルの保存・再利用.h5形式で保存し、Streamlit等へ展開可能
単一画像の分類テスト実運用を想定したスクリプト形式

🌱 応用例


week11

こちらが、データ拡張(Data Augmentation) にフォーカスしたノートブック
week11_data_aug.ipynb の内容です。

この週では、農業データにありがちな「データ不足・偏り」を解消するため、Keras の ImageDataGenerator を用いた拡張や、Albumentationsライブラリの利用にも触れていきます。

🌿 week11_data_aug.ipynb: 画像データの拡張(Data Augmentation)

# week11_data_aug.ipynb:データ拡張による画像分類精度向上

import os
import matplotlib.pyplot as plt
import numpy as np
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.preprocessing import image

# --- 拡張前の画像を確認 ---
img_path = '/content/drive/MyDrive/datasets/leaf_images/healthy/001.jpg'
img = image.load_img(img_path, target_size=(128, 128))
img_array = image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0)

plt.imshow(img.astype("uint8"))
plt.title("Original Image")
plt.axis('off')
plt.show()

# --- ImageDataGenerator による拡張 ---
datagen = ImageDataGenerator(
    rotation_range=40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    fill_mode='nearest'
)

# --- 拡張画像の表示 ---
aug_iter = datagen.flow(img_array, batch_size=1)

plt.figure(figsize=(12, 6))
for i in range(6):
    plt.subplot(2, 3, i+1)
    batch = next(aug_iter)
    image_aug = batch[0].astype("uint8")
    plt.imshow(image_aug)
    plt.axis('off')
    plt.title(f'Augmented {i+1}')
plt.suptitle('🌿 Image Augmentation Samples')
plt.show()

✅ 発展:Albumentationsを使ったカスタム拡張(任意)

# インストール(初回のみ)
!pip install -q albumentations

import albumentations as A
from PIL import Image

# --- 拡張パイプライン ---
transform = A.Compose([
    A.RandomCrop(width=120, height=120),
    A.HorizontalFlip(p=0.5),
    A.RandomBrightnessContrast(p=0.2),
    A.Rotate(limit=40),
    A.Resize(128, 128)
])

# --- 拡張適用 ---
img_pil = Image.open(img_path).convert("RGB")
img_np = np.array(img_pil)

augmented = transform(image=img_np)['image']
plt.imshow(augmented)
plt.title("Albumentations Example")
plt.axis('off')
plt.show()

🔍 この週で学べること

技術内容
ImageDataGeneratorKeras標準のリアルタイム拡張
Albumentations高速で多彩な拡張手法(Pytorchにも対応)
実装パターン可視化/保存/訓練データへの導入方法

🌾 農業での応用例

💡 次につなげる提案


week12

こちらが、転移学習(Transfer Learning) を使って、学習済みモデル(例:MobileNetV2)を農業の画像分類に応用するノートブック
week12_transfer_learning.ipynb の内容です。

🚀 week12_transfer_learning.ipynb: 転移学習による精度向上

# week12_transfer_learning.ipynb:学習済みモデルを活用した葉の分類

import tensorflow as tf
from tensorflow.keras.applications import MobileNetV2
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt

# --- Google Drive をマウント(データ/保存先用) ---
from google.colab import drive
drive.mount('/content/drive')

# --- データセット準備 ---
data_dir = '/content/drive/MyDrive/datasets/leaf_images/'  # healthy / diseased フォルダあり
img_size = (160, 160)
batch_size = 32

datagen = ImageDataGenerator(rescale=1./255, validation_split=0.2)

train_gen = datagen.flow_from_directory(
    data_dir,
    target_size=img_size,
    batch_size=batch_size,
    class_mode='binary',
    subset='training'
)

val_gen = datagen.flow_from_directory(
    data_dir,
    target_size=img_size,
    batch_size=batch_size,
    class_mode='binary',
    subset='validation'
)

# --- 転移学習モデル構築 ---
base_model = MobileNetV2(input_shape=img_size + (3,), include_top=False, weights='imagenet')
base_model.trainable = False  # 転移学習の基本:特徴抽出部分は固定

x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(64, activation='relu')(x)
output = Dense(1, activation='sigmoid')(x)

model = Model(inputs=base_model.input, outputs=output)

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

# --- 学習 ---
history = model.fit(train_gen, validation_data=val_gen, epochs=5)

# --- 学習結果の可視化 ---
plt.plot(history.history['accuracy'], label='Train Acc')
plt.plot(history.history['val_accuracy'], label='Val Acc')
plt.legend()
plt.title('Transfer Learning Accuracy')
plt.show()

🔄 Fine-tuning(オプション)

# --- base_modelの一部を再学習可能に ---
base_model.trainable = True

# 最後の数層のみ再学習する(例:100層以降)
fine_tune_at = 100
for layer in base_model.layers[:fine_tune_at]:
    layer.trainable = False

model.compile(optimizer=tf.keras.optimizers.Adam(1e-5),
              loss='binary_crossentropy',
              metrics=['accuracy'])

fine_tune_epochs = 5
history_fine = model.fit(train_gen, validation_data=val_gen, epochs=fine_tune_epochs)

# --- 再学習後の精度表示 ---
plt.plot(history_fine.history['accuracy'], label='Train Acc (fine)')
plt.plot(history_fine.history['val_accuracy'], label='Val Acc (fine)')
plt.legend()
plt.title('Fine-Tuning Accuracy')
plt.show()

📌 この週の習得ポイント

項目内容
転移学習の基本学習済みCNN(MobileNetV2)の利用方法
特徴抽出 vs 再学習base_modelのtrainableの切替
少ないデータでの高精度実用性・少量データの応用に強い

🌿 農業での応用例

こちらが、モデルの評価に関するノートブック、 week13_model_eval.ipynb の内容です。

📊 week13_model_eval.ipynb: モデル評価と評価指標の理解

# week13_model_eval.ipynb:モデルの評価と評価指標の計算

import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix, classification_report
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing import image
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# --- モデル読み込み ---
model_path = '/content/drive/MyDrive/models/leaf_cnn_model.h5'
model = load_model(model_path)

# --- データ準備 ---
data_dir = '/content/drive/MyDrive/datasets/leaf_images/'
img_size = (160, 160)
batch_size = 32

datagen = ImageDataGenerator(rescale=1./255, validation_split=0.2)

val_gen = datagen.flow_from_directory(
    data_dir,
    target_size=img_size,
    batch_size=batch_size,
    class_mode='binary',
    subset='validation'
)

# --- モデル評価 ---
loss, accuracy = model.evaluate(val_gen)
print(f"Loss: {loss:.4f}, Accuracy: {accuracy:.4f}")

# --- 混同行列の計算 ---
val_pred = model.predict(val_gen)
val_pred = (val_pred > 0.5).astype("int32")  # 0.5で2クラス分類

true_labels = val_gen.classes
cm = confusion_matrix(true_labels, val_pred)

# --- 混同行列の表示 ---
plt.figure(figsize=(8, 6))
plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)
plt.title('Confusion Matrix')
plt.colorbar()
classes = ['Healthy', 'Diseased']
plt.xticks(np.arange(len(classes)), classes, rotation=45)
plt.yticks(np.arange(len(classes)), classes)
plt.ylabel('True label')
plt.xlabel('Predicted label')
plt.tight_layout()
plt.show()

# --- 分類レポート ---
report = classification_report(true_labels, val_pred, target_names=classes)
print(report)

📌 評価のポイント

評価項目内容
評価指標Loss, Accuracy などの基本評価指標
混同行列モデルの誤分類を視覚化して理解
分類レポート精度、再現率、F1スコアを一目で確認
2クラス分類threshold を用いた分類の精度評価

🌿 農業での応用例


week14

こちらが、YOLO(You Only Look Once)による物体検出に関するノートブック、
week14_yolo_intro.ipynb の内容です。

🧠 week14_yolo_intro.ipynb: YOLOによる物体検出の入門

# week14_yolo_intro.ipynb:YOLO(You Only Look Once)を用いた物体検出

import cv2
import numpy as np
import matplotlib.pyplot as plt

# --- YOLOの設定 ---
yolo_cfg = '/content/drive/MyDrive/yolov3/yolov3.cfg'
yolo_weights = '/content/drive/MyDrive/yolov3/yolov3.weights'
yolo_names = '/content/drive/MyDrive/yolov3/coco.names'

# --- YOLOネットワークの読み込み ---
net = cv2.dnn.readNetFromDarknet(yolo_cfg, yolo_weights)
layer_names = net.getLayerNames()
output_layers = [layer_names[i-1] for i in net.getUnconnectedOutLayers()]

# --- 画像読み込みと前処理 ---
image_path = '/content/drive/MyDrive/datasets/test_image.jpg'
img = cv2.imread(image_path)
height, width, channels = img.shape

# YOLO用に画像の前処理
blob = cv2.dnn.blobFromImage(img, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
net.setInput(blob)

# --- 物体検出の実行 ---
outs = net.forward(output_layers)

# --- 検出結果の解析 ---
class_ids = []
confidences = []
boxes = []
conf_threshold = 0.5  # 信頼度の閾値
nms_threshold = 0.4   # 非最大抑制の閾値

for out in outs:
    for detection in out:
        scores = detection[5:]
        class_id = np.argmax(scores)
        confidence = scores[class_id]
        
        if confidence > conf_threshold:
            center_x = int(detection[0] * width)
            center_y = int(detection[1] * height)
            w = int(detection[2] * width)
            h = int(detection[3] * height)
            
            # バウンディングボックスの座標
            x = int(center_x - w / 2)
            y = int(center_y - h / 2)
            
            boxes.append([x, y, w, h])
            confidences.append(float(confidence))
            class_ids.append(class_id)

# --- 非最大抑制(NMS)の適用 ---
indices = cv2.dnn.NMSBoxes(boxes, confidences, conf_threshold, nms_threshold)

# --- 結果の描画 ---
font = cv2.FONT_HERSHEY_SIMPLEX
colors = np.random.uniform(0, 255, size=(len(class_ids), 3))

for i in range(len(boxes)):
    if i in indices:
        x, y, w, h = boxes[i]
        label = str(class_ids[i])
        confidence = confidences[i]
        color = colors[i]
        
        # バウンディングボックスとラベルの描画
        cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)
        cv2.putText(img, f'{label} {confidence:.2f}', (x, y - 10), font, 0.5, color, 2)

# 結果の表示
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title('YOLO Object Detection')
plt.axis('off')
plt.show()

🔑 この週で学べること

内容詳細
YOLOの基本物体検出モデル(YOLO)の読み込みと実行方法
物体検出の流れ画像の前処理、物体検出、バウンディングボックスの生成
NMS(非最大抑制)重複した検出結果を減らす手法
画像処理の実践OpenCVを用いた物体検出結果の可視化

🌿 農業での応用例

🌱 次につなげる提案

このノートブックを基に、次週はYOLOを使った訓練や農業データへの適用について進めることができます!


week15

こちらが、農業向けYOLO物体検出モデルに特化したノートブック、
week15_yolo_agri.ipynb の内容です。

🌾 week15_yolo_agri.ipynb: 農業データに特化したYOLO物体検出

# week15_yolo_agri.ipynb:農業向けYOLOを用いた作物検出

import cv2
import numpy as np
import matplotlib.pyplot as plt

# --- YOLOの設定(農業専用のデータセット) ---
yolo_cfg = '/content/drive/MyDrive/yolov3/yolov3_agri.cfg'
yolo_weights = '/content/drive/MyDrive/yolov3/yolov3_agri.weights'
yolo_names = '/content/drive/MyDrive/yolov3/agri_classes.names'

# --- YOLOネットワークの読み込み ---
net = cv2.dnn.readNetFromDarknet(yolo_cfg, yolo_weights)
layer_names = net.getLayerNames()
output_layers = [layer_names[i-1] for i in net.getUnconnectedOutLayers()]

# --- 農業画像の読み込み ---
image_path = '/content/drive/MyDrive/datasets/agri_test_image.jpg'  # 農作物の画像
img = cv2.imread(image_path)
height, width, channels = img.shape

# YOLO用に画像の前処理
blob = cv2.dnn.blobFromImage(img, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
net.setInput(blob)

# --- 物体検出の実行 ---
outs = net.forward(output_layers)

# --- 検出結果の解析 ---
class_ids = []
confidences = []
boxes = []
conf_threshold = 0.5  # 信頼度の閾値
nms_threshold = 0.4   # 非最大抑制の閾値

for out in outs:
    for detection in out:
        scores = detection[5:]
        class_id = np.argmax(scores)
        confidence = scores[class_id]
        
        if confidence > conf_threshold:
            center_x = int(detection[0] * width)
            center_y = int(detection[1] * height)
            w = int(detection[2] * width)
            h = int(detection[3] * height)
            
            # バウンディングボックスの座標
            x = int(center_x - w / 2)
            y = int(center_y - h / 2)
            
            boxes.append([x, y, w, h])
            confidences.append(float(confidence))
            class_ids.append(class_id)

# --- 非最大抑制(NMS)の適用 ---
indices = cv2.dnn.NMSBoxes(boxes, confidences, conf_threshold, nms_threshold)

# --- 結果の描画 ---
font = cv2.FONT_HERSHEY_SIMPLEX
colors = np.random.uniform(0, 255, size=(len(class_ids), 3))

# 農業特有のクラス名
with open(yolo_names, 'r') as f:
    classes = f.read().strip().split('\n')

for i in range(len(boxes)):
    if i in indices:
        x, y, w, h = boxes[i]
        label = str(classes[class_ids[i]])
        confidence = confidences[i]
        color = colors[i]
        
        # バウンディングボックスとラベルの描画
        cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)
        cv2.putText(img, f'{label} {confidence:.2f}', (x, y - 10), font, 0.5, color, 2)

# 結果の表示
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title('YOLO Object Detection - Agriculture')
plt.axis('off')
plt.show()

📌 この週で学べること

内容詳細
農業特有のクラス農作物や病害虫、作物の状態などを識別するクラス
カスタマイズされたYOLOモデル農業向けにトレーニングされたYOLOモデルの使い方
農業画像の物体検出農作物、果物、病害の検出とバウンディングボックスの描画

🌾 農業での応用例

💡 今後の展開


week16

こちらが、作物の病害分類に特化したノートブック、
week16_disease_classify.ipynb の内容です。

🦠 week16_disease_classify.ipynb: 作物の病害分類モデル(CNN)

# week16_disease_classify.ipynb:病気画像分類(例:葉の病害)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
from sklearn.metrics import classification_report, confusion_matrix

# --- データセットの準備 ---
# ディレクトリ構成(例):
# /content/drive/MyDrive/datasets/leaf_disease/
# ├── train/
# │   ├── healthy/
# │   └── diseased/
# └── val/
#     ├── healthy/
#     └── diseased/

train_dir = '/content/drive/MyDrive/datasets/leaf_disease/train'
val_dir = '/content/drive/MyDrive/datasets/leaf_disease/val'

img_size = (128, 128)
batch_size = 32

train_datagen = ImageDataGenerator(rescale=1./255)
val_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
    train_dir,
    target_size=img_size,
    batch_size=batch_size,
    class_mode='binary'
)

val_generator = val_datagen.flow_from_directory(
    val_dir,
    target_size=img_size,
    batch_size=batch_size,
    class_mode='binary'
)

# --- モデル構築(CNN) ---
model = Sequential([
    Conv2D(32, (3, 3), activation='relu', input_shape=(128, 128, 3)),
    MaxPooling2D(2, 2),
    Conv2D(64, (3, 3), activation='relu'),
    MaxPooling2D(2, 2),
    Flatten(),
    Dense(128, activation='relu'),
    Dropout(0.3),
    Dense(1, activation='sigmoid')
])

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

# --- モデル学習 ---
history = model.fit(
    train_generator,
    epochs=10,
    validation_data=val_generator
)

# --- 学習の可視化 ---
plt.plot(history.history['accuracy'], label='Train Acc')
plt.plot(history.history['val_accuracy'], label='Val Acc')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.title('Disease Classification Accuracy')
plt.legend()
plt.show()

# --- モデル評価 ---
val_generator.reset()
preds = model.predict(val_generator, verbose=1)
y_pred = (preds > 0.5).astype('int32').flatten()
y_true = val_generator.classes

print(classification_report(y_true, y_pred))
print("Confusion Matrix:")
print(confusion_matrix(y_true, y_pred))

🔍 この週の学習内容まとめ

学習項目説明
CNN構築の基礎畳み込み、プーリング、全結合層などの使い方
データ前処理ImageDataGeneratorでの画像スケーリング
学習・評価・可視化精度のグラフ描画、分類レポート、混同行列
クラス分類健康な葉 vs 病害を受けた葉の分類

🌿 応用例(農業)

💡 次のステップ案