【淫ミュ】YAJU&Uと淫夢と野獣先輩に寄り添い続けるソリューション




# はじめに

近年、ネット上で密かに注目を集めているのが、かつて親しまれた知育コンテンツ「810先輩」の再評価です。  
YouTubeやSNS上ではその淫夢の平成レトロかつ独特な雰囲気に魅了される声が多く、再ブームと呼べる盛り上がりを見せています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043781/480c2507-3985-4d4f-abf3-e488938f15cc.png)


 [参考動画はこちら1](https://youtu.be/lEz_NjJs4dk?si=yd3nmcKhauUwEoOb)
 
 [参考動画はこちら2](https://www.youtube.com/watch?v=niKAylKNIEI)

一方で、淫夢コンテンツのテンプレート化も同時に進行しており、「どれも似ている」「中身が薄く感じる」といった“飽和感”が広がりつつあるのも事実です。情報があふれる時代だからこそ、「選ばれる学び」には個性と体験の深さが求められていると感じます。


私たちはいま、改めて「日本発の知育・教育コンテンツ」に宿る力を見直しています。

それは単なるニコニコ動画によるノスタルジーではありません。  一人ひとりの子どもたちや保護者に寄り添いながら、知的好奇心と探究心を引き出すような、  “個性”と“発見”を軸にした教育DX支援の形です。

その実現のために、私たちは以下のテクノロジーを積極的に活用しています：

-  **信号処理とAI（機械学習）をベースにした教材**
-  **Pythonによる可視化・データ分析**
-  **Google Colab上で誰でもすぐに実行可能なコード例**
 [紹介動画はこちら](https://youtu.be/uT5J6PLTpMY?si=5U4jxnWRqrOpFVV1)
-  **プロンプトエンジニアリングによるアジャイルな学習体験**




##  お客様に提供するPythonベース・アジャイルソリューション


-  **ソリューション1：FFT変換＆フィルタ画像処理とローパス・ハイパス・8ビット量子化と顔認識（カスケード分類器)を一括体験**



```Python
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import cv2
from google.colab import files

# ------------------------------
# Upload image file
# ------------------------------
uploaded = files.upload()
filename = list(uploaded.keys())[0]

# ------------------------------
# Load image and convert to grayscale
# ------------------------------
img = Image.open(filename).convert('L')
img_array = np.array(img)

# ------------------------------
# FFT
# ------------------------------
f = np.fft.fft2(img_array)
fshift = np.fft.fftshift(f)
magnitude_spectrum = 20 * np.log(np.abs(fshift) + 1)

# ------------------------------
# Low-pass filter
# ------------------------------
rows, cols = img_array.shape
crow, ccol = rows // 2, cols // 2
r = 50

lowpass_mask = np.zeros((rows, cols), dtype=np.uint8)
cv = np.ogrid[:rows, :cols]
distance = (cv[0] - crow)**2 + (cv[1] - ccol)**2
lowpass_mask[distance <= r**2] = 1

f_lowpass = fshift * lowpass_mask
img_lowpass = np.abs(np.fft.ifft2(np.fft.ifftshift(f_lowpass)))
img_lowpass_q = np.clip(np.round(img_lowpass), 0, 255).astype(np.uint8)

# ------------------------------
# High-pass filter
# ------------------------------
highpass_mask = 1 - lowpass_mask
f_highpass = fshift * highpass_mask
img_highpass = np.abs(np.fft.ifft2(np.fft.ifftshift(f_highpass)))
img_highpass_q = np.clip(np.round(img_highpass), 0, 255).astype(np.uint8)

# ------------------------------
# AD conversion (8-bit quantization)
# ------------------------------
img_ad = np.clip(np.round(img_array), 0, 255).astype(np.uint8)

# ------------------------------
# Face Detection using Haar Cascade
# ------------------------------
img_for_face = np.stack([img_array]*3, axis=-1).astype(np.uint8)
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
faces = face_cascade.detectMultiScale(img_array, scaleFactor=1.1, minNeighbors=5)

for (x, y, w, h) in faces:
    cv2.rectangle(img_for_face, (x, y), (x+w, y+h), (255, 0, 0), 2)

# ------------------------------
# Image Derivative (Sobel)
# ------------------------------
sobel_x = cv2.Sobel(img_array, cv2.CV_64F, 1, 0, ksize=3)
sobel_y = cv2.Sobel(img_array, cv2.CV_64F, 0, 1, ksize=3)
sobel_mag = np.sqrt(sobel_x**2 + sobel_y**2)
sobel_mag = np.clip(sobel_mag, 0, 255).astype(np.uint8)

# ------------------------------
# Image Integral (Cumulative Sum)
# ------------------------------
img_integral = np.cumsum(np.cumsum(img_array, axis=0), axis=1)
img_integral_scaled = np.log1p(img_integral)  # log scale for visualization
img_integral_scaled = np.clip((img_integral_scaled / np.max(img_integral_scaled)) * 255, 0, 255).astype(np.uint8)

# ------------------------------
# Plot all results
# ------------------------------
plt.figure(figsize=(20, 10))

titles = [
    'Original Image', 'FFT Magnitude Spectrum', 'Low-pass Filtered',
    'High-pass Filtered', '8-bit Quantized (AD)', 'Face Detection',
    'Image Derivative (Sobel)', 'Image Integral (Cumsum)'
]
images = [
    img_array, magnitude_spectrum, img_lowpass_q, img_highpass_q,
    img_ad, cv2.cvtColor(img_for_face, cv2.COLOR_BGR2RGB),
    sobel_mag, img_integral_scaled
]

for i in range(len(images)):
    plt.subplot(2, 4, i+1)
    cmap = 'gray' if images[i].ndim == 2 else None
    plt.imshow(images[i], cmap=cmap)
    plt.title(titles[i])
    plt.axis('off')

plt.tight_layout()
plt.show()


```
**結果**
![スクリーンショット 2025-03-24 150127.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043781/62876dfb-a7ce-404b-9953-8cdc0f87f5ff.png)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043781/8383b9da-065c-45b3-adf9-7f4557137b2d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043781/f42702d1-329d-4a2d-b0a9-e5ed3dafd98d.png)


-  **ソリューション2：音声データのスペクトル分析ツール（FFT + STFT）**
お客様に「やりますねぇ！」の波形を提供！

```Python
# ===============================================
# 音声波形表示・STFT・FFT解析ツール（Colab用）
# Audio waveform, STFT, and FFT analyzer (for Colab)
# ===============================================

# ------------------------------
# 必要なライブラリをインストール
# Install required libraries
# ------------------------------
!pip install librosa
!pip install matplotlib
!pip install ipywidgets

# ------------------------------
# 音声ファイルをアップロード
# Upload an audio file
# ------------------------------
from google.colab import files
from IPython.display import Audio, display
import ipywidgets as widgets

uploaded = files.upload()

# ------------------------------
# ライブラリのインポート
# Import libraries
# ------------------------------
import librosa
import librosa.display
import matplotlib.pyplot as plt
import numpy as np

# ------------------------------
# アップロードしたファイル名を指定
# Specify the uploaded file name
# ------------------------------
file_name = 'Yarimasune.wav'  # Replace with your uploaded file name

# ------------------------------
# 音声ファイルを読み込む（元のサンプリングレートを保持）
# Load audio with original sampling rate
# ------------------------------
y, sr = librosa.load(file_name, sr=None)

# ------------------------------
# 音声波形をプロット
# Plot the audio waveform
# ------------------------------
plt.figure(figsize=(10, 6))
librosa.display.waveshow(y, sr=sr)
plt.title("Waveform of the Audio Signal")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.show()

# ------------------------------
# 音声を再生するボタンを作成
# Create a playback button
# ------------------------------
def play_audio(_):
    display(Audio(file_name))

play_button = widgets.Button(description="Play Audio")
play_button.on_click(play_audio)
display(play_button)

# ------------------------------
# 短時間フーリエ変換（STFT）を実行
# Compute Short-Time Fourier Transform (STFT)
# ------------------------------
D = librosa.stft(y)
D_db = librosa.amplitude_to_db(np.abs(D), ref=np.max)

# ------------------------------
# スペクトログラムをプロット（STFT）
# Plot the spectrogram (STFT)
# ------------------------------
plt.figure(figsize=(10, 6))
librosa.display.specshow(D_db, sr=sr, x_axis='time', y_axis='log')
plt.colorbar(format='%+2.0f dB')
plt.title("Spectrogram (STFT) of the Audio Signal")
plt.xlabel("Time (s)")
plt.ylabel("Frequency (Hz)")
plt.show()

# ------------------------------
# FFTを実行（音声全体に対して）
# Apply FFT to the entire signal
# ------------------------------
fft_result = np.fft.fft(y)
fft_freq = np.fft.fftfreq(len(y), 1 / sr)
fft_magnitude = np.abs(fft_result)

# ------------------------------
# 正の周波数成分のみを抽出
# Use only the positive frequency components
# ------------------------------
positive_freqs = fft_freq[:len(fft_freq) // 2]
positive_magnitude = fft_magnitude[:len(fft_magnitude) // 2]

# ------------------------------
# FFT結果をプロット
# Plot the FFT result
# ------------------------------
plt.figure(figsize=(10, 6))
plt.plot(positive_freqs, positive_magnitude)
plt.title("FFT of the Audio Signal")
plt.xlabel("Frequency (Hz)")
plt.ylabel("Magnitude")
plt.grid(True)
plt.show()



```

**結果**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043781/018c4516-af03-42d8-b14b-9048274d990f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043781/bbf4a7e9-f8fc-41f2-afd6-62e12dd8d227.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043781/602975ae-0498-41bf-95a6-d0c2152f2efc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043781/e144b131-a6f7-4acc-a3b2-99068433c265.png)










-  **ソリューション3：ルールベースAIによる汚い因数分解サービス**
```Python

def prime_factors(n):
    """
    素因数分解を行う関数 / Function to compute prime factors
    引数 n を素因数に分解し、そのリストを返します。
    Returns a list of prime factors of the input number n.
    """
    factors = []  # 結果を格納するリスト / List to store the result

    # 2で割れる限り割る / Divide by 2 as long as possible
    while n % 2 == 0:
        factors.append(2)
        n //= 2

    # 3以上の奇数の因数を調べる / Check for odd factors starting from 3
    factor = 3
    while factor * factor <= n:
        while n % factor == 0:
            factors.append(factor)
            n //= factor
        factor += 2  # 次の奇数に進む / Move to the next odd number

    # 残ったnが1より大きければ、それも素因数 / If remaining n is greater than 1, it's a prime factor
    if n > 1:
        factors.append(n)

    return factors

# 対象の数値リスト / List of target numbers
numbers = [1919, 810, 114514]

# 各数値について素因数分解を実行 / Run prime factorization for each number
for number in numbers:
    result = prime_factors(number)
    print(f"{number} の素因数分解 / Prime factorization of {number}: {result}")


```

**結果**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043781/3225aa08-e1e9-430c-84ce-a4116ce3d250.png)

-  **ソリューション4：MNISTデータセットから手書き数字の「8」「1」「0」を抽出して並べて表示するサービス**
```Python
import matplotlib.pyplot as plt
from torchvision import datasets, transforms

# MNISTのデータ取得（必要ならダウンロード）
mnist_data = datasets.MNIST(root='./data', train=True, download=True, transform=transforms.ToTensor())

# 手書き数字「8」「1」「0」の画像を1枚ずつ取得
def get_digit_image(digit):
    for img, label in mnist_data:
        if label == digit:
            return img.squeeze().numpy()  # (1, 28, 28) → (28, 28)

img_8 = get_digit_image(8)
img_1 = get_digit_image(1)
img_0 = get_digit_image(0)

# プロットして並べて表示
plt.figure(figsize=(6, 2))
for i, (img, label) in enumerate(zip([img_8, img_1, img_0], ['8', '1', '0'])):
    plt.subplot(1, 3, i+1)
    plt.imshow(img, cmap='gray')
    plt.title(f"Label: {label}")
    plt.axis('off')

plt.tight_layout()
plt.show()


```


**結果**


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043781/adbeb0b0-502f-41c3-a9e0-9633c2d0b0f7.png)

-  **ソリューション5：（BERTベース）を用いてテキストをベクトル化し、コサイン類似度を代行計算するサービス**
```Python
# 必要なライブラリをインストール（初回のみ）
# !pip install -U sentence-transformers

from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

# ------------------------------
# 文の定義 / Define sentences
# ------------------------------
sentences = [
    "AI",                   # 一般的な人工知能に関する語
    "淫夢",                 # インターネットミーム
    "やりますね",          # 810先輩の代表的なセリフ
]

# ------------------------------
# モデルの読み込み / Load transformer model
# ------------------------------
model = SentenceTransformer('paraphrase-MiniLM-L6-v2')  # 軽量かつ高精度

# ------------------------------
# 埋め込みベクトルの生成 / Generate embeddings
# ------------------------------
embeddings = model.encode(sentences)

# ------------------------------
# コサイン類似度の計算 / Compute cosine similarity
# ------------------------------
similarity_matrix = cosine_similarity(embeddings)

# ------------------------------
# 結果の表示 / Print results
# ------------------------------
print("コサイン類似度（Cosine Similarity）マトリクス：\n")
for i in range(len(sentences)):
    for j in range(len(sentences)):
        print(f"{sentences[i]} vs {sentences[j]} = {similarity_matrix[i][j]:.4f}")
    print()

```
**結果**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043781/ad7355bb-9083-4655-b5c4-ea63b6e05f78.png)





-  **ソリューション6：114514, 810, 893 からなる3×3の上三角行列を変換するサービス**
```Python

import numpy as np
import sympy as sp

# ------------------------------
# 行列の定義 / Define the matrix
# ------------------------------
A = sp.Matrix([
    [114514, 810, 0],
    [0, 893, 0],
    [0, 0, 810]
])

print("【行列 A】")
sp.pprint(A)

# ------------------------------
# 逆行列の計算 / Inverse matrix
# ------------------------------
if A.det() != 0:
    A_inv = A.inv()
    print("\n【逆行列 A⁻¹】")
    sp.pprint(A_inv)
else:
    print("\n【逆行列】存在しません（行列式 = 0）")

# ------------------------------
# 固有値と固有ベクトル / Eigenvalues & Eigenvectors
# ------------------------------
try:
    P, D = A.diagonalize()
    print("\n【対角化】")
    print("P（固有ベクトルの行列）:")
    sp.pprint(P)
    print("\nD（対角行列）:")
    sp.pprint(D)

    # 検算：A = P D P⁻¹
    A_reconstructed = P * D * P.inv()
    print("\n【検算】A = P D P⁻¹:")
    sp.pprint(A_reconstructed)
except:
    print("\n【対角化】できません（ジョルダン標準形などが必要な場合あり）")

# ------------------------------
# 転置 / Transpose
# ------------------------------
A_T = A.transpose()
print("\n【転置行列 Aᵀ】")
sp.pprint(A_T)

# ------------------------------
# トレース（跡） / Trace
# ------------------------------
trace_A = A.trace()
print("\n【トレース Tr(A)】")
print(trace_A)

# ------------------------------
# 行列式 / Determinant
# ------------------------------
det_A = A.det()
print("\n【行列式 det(A)】")
print(det_A)

# ------------------------------
# ランク / Rank
# ------------------------------
rank_A = A.rank()
print("\n【ランク Rank(A)】")
print(rank_A)

# ------------------------------
# 特異値分解（SVD は sympy 非対応） → NumPyで数値的に処理
# ------------------------------
A_np = np.array(A).astype(float)
U, S, Vt = np.linalg.svd(A_np)

print("\n【特異値分解 SVD】")
print("U =\n", U)
print("S =\n", S)
print("V^T =\n", Vt)



```
**結果**
【逆行列 A⁻¹】
⎡           -405          ⎤
⎢1/114514  ────────    0  ⎥
⎢          51130501       ⎥
⎢                         ⎥
⎢   0       1/893      0  ⎥
⎢                         ⎥
⎣   0         0      1/810⎦

【対角化】
P（固有ベクトルの行列）:
⎡0   -810   1⎤
⎢            ⎥
⎢0  113621  0⎥
⎢            ⎥
⎣1    0     0⎦

D（対角行列）:
⎡810   0     0   ⎤
⎢                ⎥
⎢ 0   893    0   ⎥
⎢                ⎥
⎣ 0    0   114514⎦

【検算】A = P D P⁻¹:
⎡114514  810   0 ⎤
⎢                ⎥
⎢  0     893   0 ⎥
⎢                ⎥
⎣  0      0   810⎦

【転置行列 Aᵀ】
⎡114514   0    0 ⎤
⎢                ⎥
⎢ 810    893   0 ⎥
⎢                ⎥
⎣  0      0   810⎦

【トレース Tr(A)】
116217

【行列式 det(A)】
82831411620

【ランク Rank(A)】
3

【特異値分解 SVD】
U =
 [[ 9.99999998e-01 -5.51599657e-05  0.00000000e+00]
 [ 5.51599657e-05  9.99999998e-01  0.00000000e+00]
 [ 0.00000000e+00  0.00000000e+00  1.00000000e+00]]
S =
 [114516.86485361    892.97765993    810.        ]
V^T =
 [[ 0.99997498  0.00707362  0.        ]
 [-0.00707362  0.99997498  0.        ]
 [ 0.          0.          1.        ]]


##  まとめ

 私たちは、喜ばれる知育コンテンツ「810先輩」に寄り添い続けながら、  
 Pythonを活用して、手軽に取り組めるDXソリューションを提供しています。  
  
動作原理の詳細な記事を書くのは少し骨が折れますので――  
 そこはプロンプトエンジニアリングの出番。  
アジャイルにeラーニングを体験しながら、  
 私たちと一緒にリスキリングの加速に取り組んでいきましょう。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043781/eec1df01-0a4b-4f49-a854-4aad6b5875db.png)



https://www.youtube.com/watch?v=9DuTlpyb9Lk

それでは