package main
import (
"fmt"
"math"
)
func main() {
// 行列のデータ
matrix := [][]float64{
{2.5, 3.7, 4.8, 1.2},
{1.0, 2.0, 3.0, 4.0},
{0.5, 1.5, 2.5, 3.5},
}
numRows := len(matrix)
numCols := len(matrix[0])
// 各列の平均を計算
averages := make([]float64, numCols)
for j := 0; j < numCols; j++ {
sum := 0.0
for i := 0; i < numRows; i++ {
sum += matrix[i][j]
}
averages[j] = sum / float64(numRows)
}
// 各列の各データと平均の差の二乗和を計算
sumOfSquaredDiffs := make([]float64, numCols)
for j := 0; j < numCols; j++ {
for i := 0; i < numRows; i++ {
diff := matrix[i][j] - averages[j]
sumOfSquaredDiffs[j] += diff * diff
}
}
// 各列の分散を計算
variances := make([]float64, numCols)
for j := 0; j < numCols; j++ {
variances[j] = sumOfSquaredDiffs[j] / float64(numRows)
}
// 各列の標準偏差を計算
stdDevs := make([]float64, numCols)
for j := 0; j < numCols; j++ {
stdDevs[j] = math.Sqrt(variances[j])
}
// 行列の各要素を標準偏差で正規化
normalizedMatrix := make([][]float64, numRows)
for i := 0; i < numRows; i++ {
normalizedMatrix[i] = make([]float64, numCols)
for j := 0; j < numCols; j++ {
normalizedMatrix[i][j] = (matrix[i][j] - averages[j]) / stdDevs[j]
}
}
// 正規化された行列を表示
fmt.Println("正規化された行列:")
for i := 0; i < numRows; i++ {
fmt.Println(normalizedMatrix[i])
}
}
Go言語で行列の各列の標準偏差を求め、その標準偏差を用いて行列を正規化するコード
現時点で、ラズパイ4(○arm64 ×amd64)のubunts22.04でChromeのインストールに失敗しています
ラズパイ4は、(○arm64 ×amd64)を採用しており、色々とトラブルとなっています。これも、その一つかどうか不明ですが、Chromeのインストールに失敗しています。
で、まあ、以下のことをごちゃごちゃしているうちに動きましたので、メモを残しておきます。
$ sudo snap refresh
$sudo snap install chromium
( $ sudo apt install -y chromium-browser は、失敗しました)
で、起動は、
$ chromium (× $ chromium-browser)
でした。
以上
PythonのGAで色々なんとかする
Pythonを使った因子分析のコード を そのまま使わせて頂いています。
【Pythonで行う】因子分析
# ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/go-efa$ python3 main3.py
# ライブラリのインポート
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
from factor_analyzer import FactorAnalyzer
# データの読み込み
df_workers = pd.read_csv("sample_factor.csv")
print(df_workers)
# 変数の標準化
df_workers_std = df_workers.apply(lambda x: (x-x.mean())/x.std(), axis=0)
# 固有値を求める
ei = np.linalg.eigvals(df_workers.corr())
print("固有値", ei)
# 因子分析の実行
fa = FactorAnalyzer(n_factors=2, rotation="promax")
fa.fit(df_workers_std)
# 因子負荷量,共通性
loadings_df = pd.DataFrame(fa.loadings_, columns=["第1因子", "第2因子"])
loadings_df.index = df_workers.columns
loadings_df["共通性"] = fa.get_communalities()
print(loadings_df)
# 因子負荷量の二乗和,寄与率,累積寄与率
var = fa.get_factor_variance()
df_var = pd.DataFrame(list(zip(var[0], var[1], var[2])),
index=["第1因子", "第2因子"],
columns=["因子負荷量の二乗和", "寄与率", "累積寄与率"])
print(df_var.T)
# バイプロットの作図
score = fa.transform(df_workers_std)
coeff = fa.loadings_.T
fa1 = 0
fa2 = 1
labels = df_workers.columns
annotations = df_workers.index
xs = score[:, fa1]
ys = score[:, fa2]
n = score.shape[1]
scalex = 1.0 / (xs.max() - xs.min())
scaley = 1.0 / (ys.max() - ys.min())
X = xs * scalex
Y = ys * scaley
for i, label in enumerate(annotations):
plt.annotate(label, (X[i], Y[i]))
for j in range(coeff.shape[1]):
plt.arrow(0, 0, coeff[fa1, j], coeff[fa2, j], color='r', alpha=0.5,
head_width=0.03, head_length=0.015)
plt.text(coeff[fa1, j] * 1.15, coeff[fa2, j] * 1.15, labels[j], color='r',
ha='center', va='center')
plt.xlim(-1, 1)
plt.ylim(-1, 1)
plt.xlabel("第1因子")
plt.ylabel("第2因子")
plt.grid()
plt.show()
Pythonを使ったGAのコード を そのまま使わせて頂いています。
【python】遺伝的アルゴリズム(Genetic Algorithm)を実装してみる
遺伝配列を0/1を、便宜的に0~4にして動くよう、一部改造させて頂いております。
# ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/go-efa$ python3 ga.py
import numpy as np
import matplotlib.pyplot as plt
class Individual:
'''各個体のクラス
args: 個体の持つ遺伝子情報(np.array)'''
def __init__(self, genom):
self.genom = genom
self.fitness = 0 # 個体の適応度(set_fitness関数で設定)
self.set_fitness()
def set_fitness(self):
'''個体に対する目的関数(OneMax)の値をself.fitnessに代入'''
self.fitness = self.genom.sum()
def get_fitness(self):
'''self.fitnessを出力'''
return self.fitness
def mutate(self):
'''遺伝子の突然変異'''
tmp = self.genom.copy()
i = np.random.randint(0, len(self.genom) - 1)
# tmp[i] = float(not self.genom[i])
tmp[i] = np.random.randint(0, 5) # 江端修正
self.genom = tmp
self.set_fitness()
def select_roulette(generation):
'''選択の関数(ルーレット方式)'''
selected = []
weights = [ind.get_fitness() for ind in generation]
norm_weights = [ind.get_fitness() / sum(weights) for ind in generation]
selected = np.random.choice(generation, size=len(generation), p=norm_weights)
return selected
def select_tournament(generation):
'''選択の関数(トーナメント方式)'''
selected = []
for i in range(len(generation)):
tournament = np.random.choice(generation, 3, replace=False)
max_genom = max(tournament, key=Individual.get_fitness).genom.copy()
selected.append(Individual(max_genom))
return selected
def crossover(selected):
'''交叉の関数'''
children = []
if POPURATIONS % 2:
selected.append(selected[0])
for child1, child2 in zip(selected[::2], selected[1::2]):
if np.random.rand() < CROSSOVER_PB:
child1, child2 = cross_two_point_copy(child1, child2)
children.append(child1)
children.append(child2)
children = children[:POPURATIONS]
return children
def cross_two_point_copy(child1, child2):
'''二点交叉'''
size = len(child1.genom)
tmp1 = child1.genom.copy()
tmp2 = child2.genom.copy()
cxpoint1 = np.random.randint(1, size)
cxpoint2 = np.random.randint(1, size - 1)
if cxpoint2 >= cxpoint1:
cxpoint2 += 1
else:
cxpoint1, cxpoint2 = cxpoint2, cxpoint1
tmp1[cxpoint1:cxpoint2], tmp2[cxpoint1:cxpoint2] = tmp2[cxpoint1:cxpoint2].copy(), tmp1[cxpoint1:cxpoint2].copy()
new_child1 = Individual(tmp1)
new_child2 = Individual(tmp2)
return new_child1, new_child2
def mutate(children):
for child in children:
if np.random.rand() < MUTATION_PB:
child.mutate()
return children
def create_generation(POPURATIONS, GENOMS):
'''初期世代の作成
return: 個体クラスのリスト'''
generation = []
for i in range(POPURATIONS):
# individual = Individual(np.random.randint(0, 2, GENOMS))
individual = Individual(np.random.randint(0, 5, GENOMS))
generation.append(individual)
return generation
def ga_solve(generation):
'''遺伝的アルゴリズムのソルバー
return: 最終世代の最高適応値の個体、最低適応値の個体'''
best = []
worst = []
# --- Generation loop
print('Generation loop start.')
for i in range(GENERATIONS):
# --- Step1. Print fitness in the generation
best_ind = max(generation, key=Individual.get_fitness)
best.append(best_ind.fitness)
worst_ind = min(generation, key=Individual.get_fitness)
worst.append(worst_ind.fitness)
print("Generation: " + str(i) \
+ ": Best fitness: " + str(best_ind.fitness) \
+ ". Worst fitness: " + str(worst_ind.fitness))
# --- Step2. Selection (Roulette)
# selected = select_roulette(generation)
selected = select_tournament(generation)
# --- Step3. Crossover (two_point_copy)
children = crossover(selected)
# --- Step4. Mutation
generation = mutate(children)
print("Generation loop ended. The best individual: ")
print(best_ind.genom)
return best, worst
np.random.seed(seed=65)
# param
POPURATIONS = 100
# GENOMS = 50 # 江端修正
GENOMS = 160
GENERATIONS = 1000
CROSSOVER_PB = 0.8
MUTATION_PB = 0.1
# create first genetarion
generation = create_generation(POPURATIONS, GENOMS)
# solve
best, worst = ga_solve(generation)
# plot
fig, ax = plt.subplots()
ax.plot(best, label='max')
ax.plot(worst, label='min')
ax.axhline(y=GENOMS, color='black', linestyle=':', label='true')
ax.set_xlim([0, GENERATIONS - 1])
#ax.set_ylim([0, GENOMS * 1.1])
ax.set_ylim([0, GENOMS * 2.2])
ax.legend(loc='best')
ax.set_xlabel('Generations')
ax.set_ylabel('Fitness')
ax.set_title('Tournament Select')
plt.show()
明日は、この2つをマージして、目的のプログラムを完成させます。
以下のプログラムは、20個のデータを使って因子分析を行い、その分析因子分析を同じ結果を生み出す200個のダミーデータを作成します。
アルゴリズムの説明は省略します(が、私は分かっています)。
まず、データ(sample_factory.csv)
x1,x2,x3,x4,x5,x6,x7,x8
2,4,4,1,3,2,2,1
5,2,1,3,1,4,2,1
2,3,4,3,4,2,4,5
2,2,2,2,3,2,2,2
5,4,3,4,4,5,4,3
1,4,4,2,4,3,2,3
3,1,1,1,1,2,1,1
5,5,3,5,4,5,3,5
1,3,4,1,3,1,3,1
4,4,3,1,4,4,2,1
3,3,3,2,4,4,4,2
1,2,1,3,1,1,1,1
5,2,3,5,2,5,1,3
4,1,1,3,1,2,2,1
1,1,1,1,2,1,2,1
3,1,2,1,1,3,2,1
1,2,3,5,2,2,2,2
3,1,1,3,2,4,2,1
3,2,3,2,2,2,2,5
1,4,3,1,4,3,5,3
以下、GAのコード
# ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/go-efa$ python3 ga-factory2.py
# ライブラリのインポート
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# import japanize_matplotlibe
from factor_analyzer import FactorAnalyzer
import matplotlib.pyplot as plt
class Individual:
'''各個体のクラス
args: 個体の持つ遺伝子情報(np.array)'''
def __init__(self, genom):
self.genom = genom
self.fitness = 0 # 個体の適応度(set_fitness関数で設定)
self.set_fitness()
def set_fitness(self):
'''個体に対する目的関数(OneMax)の値をself.fitnessに代入'''
# まずgenomを行列にデータに変換する
# self.fitness = self.genom.sum()
# 遺伝子列を行列に変換
arr2d = self.genom.reshape((-1, 8)) # 列が分からない場合は、-1にするとよい
# 各列の平均と標準偏差を計算
mean = np.mean(arr2d, axis=0)
std = np.std(arr2d, axis=0)
# 標準偏差値に変換
standardized_arr2d = (arr2d - mean) / std
# 因子分析の実行
fa_arr2d = FactorAnalyzer(n_factors=2, rotation="promax")
fa_arr2d.fit(standardized_arr2d)
# 因子分析行列の算出
loadings_arr2d = fa_arr2d.loadings_
# 因子分析行列の差分算出
distance2 = euclidean_distance(fa.loadings_, loadings_arr2d)
# print(distance2)
# とりあえず評価関数をこの辺から始めてみる
self.fitness = 1 / distance2
def get_fitness(self):
'''self.fitnessを出力'''
return self.fitness
def mutate(self):
'''遺伝子の突然変異'''
tmp = self.genom.copy()
i = np.random.randint(0, len(self.genom) - 1)
# tmp[i] = float(not self.genom[i])
tmp[i] = np.random.randint(1, 6) # 江端修正
self.genom = tmp
self.set_fitness()
def euclidean_distance(matrix_a, matrix_b):
# 行列Aと行列Bの要素ごとの差を計算します
diff = matrix_a - matrix_b
# 差の二乗を計算します
squared_diff = np.square(diff)
# 差の二乗の和を計算します
sum_squared_diff = np.sum(squared_diff)
# 和の平方根を計算します
distance = np.sqrt(sum_squared_diff)
return distance
def select_roulette(generation):
'''選択の関数(ルーレット方式)'''
selected = []
weights = [ind.get_fitness() for ind in generation]
norm_weights = [ind.get_fitness() / sum(weights) for ind in generation]
selected = np.random.choice(generation, size=len(generation), p=norm_weights)
return selected
def select_tournament(generation):
'''選択の関数(トーナメント方式)'''
selected = []
for i in range(len(generation)):
tournament = np.random.choice(generation, 3, replace=False)
max_genom = max(tournament, key=Individual.get_fitness).genom.copy()
selected.append(Individual(max_genom))
return selected
def crossover(selected):
'''交叉の関数'''
children = []
if POPURATIONS % 2:
selected.append(selected[0])
for child1, child2 in zip(selected[::2], selected[1::2]):
if np.random.rand() < CROSSOVER_PB:
child1, child2 = cross_two_point_copy(child1, child2)
children.append(child1)
children.append(child2)
children = children[:POPURATIONS]
return children
def cross_two_point_copy(child1, child2):
'''二点交叉'''
size = len(child1.genom)
tmp1 = child1.genom.copy()
tmp2 = child2.genom.copy()
cxpoint1 = np.random.randint(1, size)
cxpoint2 = np.random.randint(1, size - 1)
if cxpoint2 >= cxpoint1:
cxpoint2 += 1
else:
cxpoint1, cxpoint2 = cxpoint2, cxpoint1
tmp1[cxpoint1:cxpoint2], tmp2[cxpoint1:cxpoint2] = tmp2[cxpoint1:cxpoint2].copy(), tmp1[cxpoint1:cxpoint2].copy()
new_child1 = Individual(tmp1)
new_child2 = Individual(tmp2)
return new_child1, new_child2
def mutate(children):
for child in children:
if np.random.rand() < MUTATION_PB:
child.mutate()
return children
def create_generation(POPURATIONS, GENOMS):
'''初期世代の作成
return: 個体クラスのリスト'''
generation = []
for i in range(POPURATIONS): # POPURATIONS = 100
# individual = Individual(np.random.randint(0, 2, GENOMS))
individual = Individual(np.random.randint(1, 6, GENOMS))
generation.append(individual)
return generation
def ga_solve(generation):
'''遺伝的アルゴリズムのソルバー
return: 最終世代の最高適応値の個体、最低適応値の個体'''
best = []
worst = []
# --- Generation loop
print('Generation loop start.')
for i in range(GENERATIONS):
# --- Step1. Print fitness in the generation
best_ind = max(generation, key=Individual.get_fitness)
best.append(best_ind.fitness)
worst_ind = min(generation, key=Individual.get_fitness)
worst.append(worst_ind.fitness)
print("Generation: " + str(i) \
+ ": Best fitness: " + str(best_ind.fitness) \
+ ". Worst fitness: " + str(worst_ind.fitness))
# --- Step2. Selection (Roulette)
# selected = select_roulette(generation)
selected = select_tournament(generation)
# --- Step3. Crossover (two_point_copy)
children = crossover(selected)
# --- Step4. Mutation
generation = mutate(children)
print("Generation loop ended. The best individual: ")
print(best_ind.genom)
return best, worst
np.random.seed(seed=65)
# param
POPURATIONS = 100 # 個体数
# GENOMS = 50 # 江端修正
# GENOMS = 160 # GENの長さ
GENOMS = 1600 # GENの長さ 1つのデータが8個の整数からなるので、合計200個のデ0タとなる
GENERATIONS = 1000
CROSSOVER_PB = 0.8
# MUTATION_PB = 0.1
MUTATION_PB = 0.3 # ミューテーションは大きい方が良いように思える
# ファイルからデータの読み込み
df_workers = pd.read_csv("sample_factor.csv")
print(df_workers)
# 変数の標準化
df_workers_std = df_workers.apply(lambda x: (x-x.mean())/x.std(), axis=0)
print(df_workers_std)
# 固有値を求める(不要と思うけど、残しておく)
ei = np.linalg.eigvals(df_workers.corr())
print(ei)
print("因子分析の実行") # 絶対必要
fa = FactorAnalyzer(n_factors=2, rotation="promax")
fa.fit(df_workers_std)
# print(fa.loadings_) # これが因子分析の行列
# 因子負荷量,共通性(不要と思うけど、残しておく)
loadings_df = pd.DataFrame(fa.loadings_, columns=["第1因子", "第2因子"])
loadings_df.index = df_workers.columns
loadings_df["共通性"] = fa.get_communalities()
# 因子負荷量の二乗和,寄与率,累積寄与率(不要と思うけど、残しておく)
var = fa.get_factor_variance()
df_var = pd.DataFrame(list(zip(var[0], var[1], var[2])),
index=["第1因子", "第2因子"],
columns=["因子負荷量の二乗和", "寄与率", "累積寄与率"])
print(df_var.T)
# create first genetarion
generation = create_generation(POPURATIONS, GENOMS)
# solve
best, worst = ga_solve(generation)
# plot
#fig, ax = plt.subplots()
#ax.plot(best, label='max')
#ax.plot(worst, label='min')
#ax.axhline(y=GENOMS, color='black', linestyle=':', label='true')
#ax.set_xlim([0, GENERATIONS - 1])
#ax.set_ylim([0, GENOMS * 1.1])
#ax.legend(loc='best')
#ax.set_xlabel('Generations')
#ax.set_ylabel('Fitness')
#ax.set_title('Tournament Select')
#plt.show()
ga-factory2.py :200固体 主成分行列からの距離は、distance2(これが一致度) 評価関数は、この逆数を使っているだけ
ga-factory3.py :2000固体
以上
「PythonからGo、GoからPythonを呼び出し合う」を勉強中
PythonからGo、GoからPythonを呼び出し合う
で、勉強させて頂いております。
私、今、超スケーラブルな高速の遺伝的アルゴリズムをGo言語で実装しようとしているのですが、計算ライブラリの充実度はPythonが圧倒しているからです。
# 私が、Go言語で計算ライブラリを自作する、というのは、却下です(面倒くさい)
まあ、これは、元を辿ると"ChatGPTの責任"とも言えるのですが(押しつけ)
取り敢えず、参照させて頂いたページのコードを、自分の環境に合わせて(といっても、結構苦労した"Python3.h"の場所が分からなかった)、ここまで動きました。
/*
環境
wsl -d Ubuntu-20.04
実行結果
ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/go-efa$ go run main1.go
Hello, World! and Ebata is great
*/
package main
// #cgo CFLAGS: -I/usr/include/python3.9
// #cgo LDFLAGS: -L/usr/lib/pytho3.9 -lpython3.9
// #include
import "C"
// import "C"のうえに改行いれるとエラーになる(信じられないが)
func main() {
// 最後にPythonインタプリタ終了
defer C.Py_Finalize()
// Pythonインタプリタの初期化
C.Py_Initialize()
// GoのstringをCのcharに型変換(変換しないとPyRun_SimpleStringに型合ってないよって怒られる)
// cannot use "print(\"Hello, World!\")" (type string) as type *_Ctype_char in argument to _Cfunc_PyRun_SimpleString
pyCodeStr := `print("Hello, World! and Ebata is great!")`
pyCodeChar := C.CString(pyCodeStr)
// Pythonコードを文字列として受け取ってインタプリタ上で実行
C.PyRun_SimpleString(pyCodeChar)
}
ようするに、このプログラムは、Go言語を使って、Pythonのインタプリタに一行づつコマンドを打ち込むプログラムのようです。
pythonのライブラリを使えるという訳でないようです。
GoとPythonをマージする方法は、どうも調子がよくないようです。
GoとPythonとGrumpyの速度ベンチマーク ~Googleのトランスパイラはどれくらい速い?~
Raspberry Pi Ubuntu Spinnaker SDK Setup
Raspberry Pi Ubuntu Spinnaker SDK Setup
Raspberry Pi Ubuntu Spinnaker SDKのセットアップ
These steps describe using an Ubuntu desktop environment to install Ubuntu and the Spinnaker Python interface on a Raspberry Pi 3 B+. Commands to be run on the desktop are prefaced with (desktop)$
, and commands to be run on the Raspberry Pi are prefaced with (pi)$
この手順では、Ubuntuデスクトップ環境を使用して、Raspberry Pi 3 B+にUbuntuとSpinnaker Pythonインターフェースをインストールする方法を説明します。デスクトップ上で実行するコマンドの前には(desktop)$を、Raspberry Pi上で実行するコマンドの前には(pi)$を付けます。
-
Flash the latest Ubuntu image (at the time of writing: 18.04) to an SD card and perform first-time setup by following these instructions. You will need an HDMI cable, a monitor, and a keyboard. The Raspberry Pi must also be connected to your local network via Ethernet.
最新のUbuntuイメージ(執筆時点では18.04)をSDカードに書き込み、以下の手順に従って初回セットアップを行う。HDMIケーブル、モニター、キーボードが必要です。また、Raspberry Piはイーサネット経由でローカルネットワークに接続されている必要があります。 - Perform basic software updates on the Pi:
Piの基本的なソフトウェアアップデートを行う:
(pi)$ sudo apt update && sudo apt upgrade
-
Go to the FLIR File Download website for your camera. The software downloads will require a free FLIR account.
お使いのカメラのフリアーファイルダウンロードサイトにアクセスします。ソフトウェアのダウンロードにはフリアーシステムズの無料アカウントが必要です。 -
On the FLIR website, find the latest Linux Ubuntu ARM Operating System packages.
フリアーシステムズのウェブサイトで、最新のLinux Ubuntu ARMオペレーティングシステムパッケージをご覧ください。 - Download the ARM64 packages for the Spinnaker SDK and Spinnaker Python Interface, and transfer them to the Raspberry Pi. Eg:
Spinnaker SDK と Spinnaker Python Interface の ARM64 パッケージをダウンロードし、Raspberry Pi に転送します。例(pi)$ ip a # check pi's ip address (desktop)$ scp spinnaker-*-pkg.tar.gz spinnaker_python-*.tar \ ubuntu@<pi's ip address>:~
- On the Raspberry Pi, untar the spinnaker sdk and enter the untarred directory
Raspberry Pi上で、spinnaker sdkをuntarし、untarしたディレクトリに入ります。 - Read the README file fully, then run the install script. Eg:
READMEファイルを十分に読んでから、インストールスクリプトを実行してください。例(pi)$ sudo sh install_spinnaker_arm.sh
- You will probably run into some dependency issues while installing the SDK. If that’s the case, missing packages can be installed manually with:
SDKのインストール中に依存関係の問題に遭遇することもあるでしょう。その場合、不足しているパッケージを手動でインストールすることができます:(pi)$ sudo apt install <name-of-missing-package>
- Change back to your home directory, untar the python interface, then untar the python 3.6 interface.
ホームディレクトリに戻り、pythonインターフェースをuntarし、python 3.6インターフェースをuntarする。(pi)$ tar -xf spinnaker_python-1.*.tar (pi)$ tar -xf spinnaker_python-1.*cp36*.tar.gz
- Read the README.txt fully, then install numpy and the Spinnaker python interface. At the time of writing, there are no precompiled wheels for numpy on Ubuntu ARM, so pip will compile the package from souce. This will take several hours, but can be sped up a bit by increasing the Pi's swap size.
README.txtを十分に読み、numpyとSpinnaker pythonインターフェースをインストールします。この記事を書いている時点では、Ubuntu ARMにはnumpy用のプリコンパイルホイールがないので、pipがソースからパッケージをコンパイルします。これには数時間かかりますが、Piのスワップサイズを大きくすることで少しスピードアップできます。(pi)$ sudo apt install dphys-swapfile # (optional) # follow the rest of the increasing swap size tutorial (optional) (pi)$ sudo apt install python3-pip (pi)$ python3 -m pip install numpy (pi)$ sudo python3 -m pip install spinnaker_python-1.*.whl
- Ensure the python module can be imported successfully:
pythonモジュールが正常にインポートできることを確認する:(pi)$ python3 -c 'import PySpin' # should take a few seconds, then exit silently
You will probably run into more dependency issues here. When you try to import PySpin with a missing dependency, you'll get an error along the lines of
No Such File: <name-of-missing-package>.so
. See step 8 for help resolving these issues.
おそらくここで依存関係の問題にもっとぶつかるでしょう。依存関係が見つからないPySpinをインポートしようとすると、No Such File: <名前-of-missing-package>.soというエラーが表示されます。このような問題の解決についてはステップ8を参照してください。 - Increase the space allocated to USB devices on the Pi. This is needed so that the images taken by the camera can fit properly within RAM. Note: This change will not persist through reboot and must be repeated.
PiのUSBデバイスに割り当てられる容量を増やす。これは、カメラで撮影された画像がRAM内に適切に収まるようにするために必要です。注意: この変更は再起動しても維持されないので、繰り返し行う必要があります。(pi)$ sudo sh -c 'echo 256 > /sys/module/usbcore/parameters/usbfs_memory_mb'
-
Connect your USB 3.1 FLIR camera to the Raspberry Pi via USB.
USB3.1フリアーシステムズのカメラをUSB経由でRaspberry Piに接続します。 - Change into the Examples directory for PySpin, and run the Acquisition.py example as root. If this succeeds, the camera will take 10 pictures and store them as JPEGs in the current directory.
PySpinのExamplesディレクトリに移動し、rootでAcquisition.pyを実行します。これが成功すると、カメラは10枚の写真を撮影し、JPEGとしてカレントディレクトリに保存します。(pi)$ cd Examples/Python3 (pi)$ sudo python3 Acquisition.py
次は、BFS-U3-89S6C-C(カメラ)をRaspberry Pi 4Bで動かす
私が購入したときは、15K円くらいだったのですが、今、倍になっています。ラズパイって高価になっているんですね ―― それはさておき。
Raspberry Pi 4Bは、USB3対応のようですが、どちらのポートか分かりません。この写真を見ると右側のようです。
(出典 https://misoji-engineer.com/archives/raspberrypi-usb3.html)
まずは、ドライバのありかを探してみました。
あきらかに、これが当たりのように見えます。
ラズパイP4の石は、ARMのようです。
https://qiita.com/memakura/items/a77137856f91d6c4db43
何がどうなっているのかは分からないけど、
https://blog.csdn.net/weixin_42088912/article/details/118225949
を参考にして、/etc/udev/rule.d/40-flir-spinnaker.rules の
SUBSYSTEM=="usb", ATTRS{idVendor}=="1e10", GROUP="flirimaging"
SUBSYSTEM=="usb", ATTRS{idVendor}=="1724", GROUP="flirimaging"
SUBSYSTEM=="usb", ATTRS{idVendor}=="1e10", GROUP="flirimaging"
SUBSYSTEM=="usb", ATTRS{idVendor}=="1724", GROUP="flirimaging"
を
SUBSYSTEM=="usb", ATTRS{idVendor}=="1e10",ATTRS{idProduct}=="4000", MODE="0777", GROUP="flirimaging"
SUBSYSTEM=="usb", ATTRS{idVendor}=="1724", GROUP="flirimaging"
としたら、やっと"USB interface0"が出てきた
けど、映像が表示されないし、「SpinView_QTの応答がありません」、とか言われる。
sudo dmesg をやると
[ 533.947639] usb 2-1: Product: Blackfly S BFS-U3-89S6C
[ 533.947652] usb 2-1: Manufacturer: FLIR
[ 533.947663] usb 2-1: SerialNumber: 0126934F
[ 600.668167] usb 2-1: reset SuperSpeed USB device number 4 using xhci_hcd
[ 709.333799] xhci_hcd 0000:01:00.0: swiotlb buffer is full (sz: 16384 bytes), total 32768 (slots), used 32687 (slots)
のようなメッセージがでてくので、
https://zenn.dev/yonishi/scraps/e735a6ef11d8b5
を参考に対応。 改善なし。
https://wpitchoune.net/tricks/raspberry_pi3_increase_swap_size.html
の対応を実施
表示に成功! 詳しくは明日 ―― つかれはてました。
BFS-U3-89S6C-C(カメラ)を先ず動かす。
- ターゲットのカメラ BFS-U3-89S6C-C
- 背景と目的
『動かすこと』が仕事だからです(それ以上は秘密です)。 - 注意
たまたま、以下の手順で動いただけで、これが正解かは分かりません。 - 手順
- USB3のセット
デバイスマネージャーを起動するドロップダウンリストを確認し、USB Root Hub (USB 3.0)を右クリック(またはタップ&ホールド)し、[Uninstall Device(デバイスのアンインストール)]を選択します(重複している場合は、1つずつすべてアンインストールしてください)。
必要であれば動作を確認し、デバイスを再起動します。再起動すると、Windows 10が自動的にUSBドライバを再インストールするはずです(私は、リブートしました)。 - TELEDYNE FLIR のページにアクセス
https://www.flir.jp/support/products/blackfly-s-usb3/#Overview あたりを叩くと、多分「アカウント作れ」と言われると思いますので、素直にアカウントを作ってログインします。 - そんでもって、https://statics.teams.cdn.office.net/evergreen-assets/safelinks/1/atp-safelinks.html から、
をダウンロードして、インストールします。
(理由はよく分かりませんが)ダウンロードした後にデバイスドライバを確認すると、デバイスがインストールされていました。 - SpinViewの起動
メニューに、SpinViewが追加されているので、そこからアプリケーションを起動します。ここをクリックします。
画面が出てくるので、以下のボタンを押して下さい。
キャリブレーションに時間がかかるようですが、こんな感じの映像が出てきました
- USB3のセット
以上
【Pythonで行う】因子分析
【Pythonで行う】因子分析
wsl -d Ubuntu-20.04 で、
ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/go-efa$ python main3.py
で実行可能。
ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/go-efa$ python main3.py
[3.61634475 2.11925085 0.87875762 0.5678116 0.37337846 0.08163572
0.15971804 0.20310295]
第1因子 第2因子 共通性
x1 -0.196394 0.917136 0.879709
x2 0.859422 0.067413 0.743150
x3 0.829155 -0.161144 0.713466
x4 -0.017808 0.558695 0.312457
x5 0.984061 -0.063608 0.972421
x6 0.180765 0.850078 0.755308
x7 0.680743 -0.064480 0.467569
x8 0.532039 0.221023 0.331916
第1因子 第2因子
因子負荷量の二乗和 3.212520 1.963477
寄与率 0.401565 0.245435
累積寄与率 0.401565 0.647000
WIndows10のWSL Ubuntu-20.04に仮想の/dev/video*を作って、Webカメラ C270n をGstreamer で表示できるようにするまでの軌跡
まず、WIndows10のWSL Ubuntu-20.04 を WSL2にしなければなりません。
でもって、さらに、このWSL2に usbのデバイスを使えるようにしなければなりません。
でもって、Gstreamの環境がインストールされていることが前提です。
と、ターゲットのカメラはこれ
Webカメラ C270n HD 720P
===== 手続の備忘録 ======
Step 1: powershellを管理者モードで立ち上げて、"
usbipd server"投入
Step 2: コマンドプロンプトから、"C:\Users\ebata>wsl -d Ubuntu-20.04"を投入
Step 3: 別のpowershellを管理者モードで立ち上げて、"
usbipd wsl attach --distribution Ubuntu-20.04 --busid 8-3"を投入
Step 4: コマンドプロンプトから、"C:\Users\ebata>sudo chmod 777 /dev/video*"を投入
これらを乗り超えて、ようやく、Gstreamer で、Webカメラの映像をループバックで表示しようとしたのですが、これが全く分からなくて、色々試しました。やけくそのトアイアンドエラー
gst-launch-1.0 videotestsrc ! videoconvert ! x264enc tune=zerolatency key-int-max=30 ! mpegtsmux ! srtserversink uri="srt://:12345" latency=500
(成功)
gst-launch-1.0 v4l2src device="/dev/video0" ! 'video/x-raw, width=640, height=480, framerate=30/1' ! videoconvert ! nv3dsink (失敗)
gst-launch-1.0 videotestsrc ! videoconvert ! video/x-raw,width=1280,height=720,framerate=30/1 ! autovideosink
gst-launch-1.0 -e filesrc location=start_up.mp4 ! videoconvert ! x264enc tune=zerolatency key-int-max=30 ! mpegtsmux ! srtserversink uri="srt://:12345" latency=500
(失敗)
gst-launch-1.0 filesrc location=start_up.mp4 ! decodebin ! videorate ! video/x-raw,framerate=30/1 ! autovideosink
(動く)
gst-launch-1.0 filesrc location=start_up.mp4 ! decodebin ! videorate ! video/x-raw,framerate=30/1 ! srtserversink uri="srt://:12345" latency=500(動く)
gst-launch-1.0 v4l2src ! videoconvert ! ximagesink (動くが、大きなブラック画面がでてきただけ)
gst-launch-1.0 v4l2src device="/dev/video0" ! videoconvert ! ximagesink
gst-launch-1.0 v4l2src device="/dev/video0" ! 'video/x-raw, width=640, height=480, framerate=30/1' ! videoconvert ! nv3dsink
gst-launch-1.0 v4l2src device="/dev/video0" ! 'video/x-raw, width=640, height=480, framerate=30/1' ! videoconvert ! ximagesink
(これは黒い画面が表示される)
gst-launch-1.0 filesrc location=start_up.mp4 ! decodebin ! videorate ! video/x-raw,framerate=1/1 ! srtserversink uri="srt://:12345" latency=500
(失敗)
00:40:58.339192/multiqueue0:src*E:SRT.c: LiveCC: payload size: 506880 exceeds maximum allowed 1316
00:40:59.339081/multiqueue0:src*E:SRT.c: LiveCC: payload size: 506880 exceeds maximum allowed 1316
00:41:00.339101/multiqueue0:src*E:SRT.c: LiveCC: payload size: 506880 exceeds maximum allowed 1316
00:41:01.339057/multiqueue0:src*E:SRT.c: LiveCC: payload size: 506880 exceeds maximum allowed 1316
gst-launch-1.0 filesrc location=start_up.mp4 ! decodebin ! videorate ! video/x-raw,framerate=1/1 ! autovideosink
(成功)
gst-launch-1.0 filesrc location=start_up.mp4 ! videoconvert ! x264enc tune=zerolatency key-int-max=30 ! mpegtsmux ! srtserversink uri="srt://:12345" latency=500
(失敗)
gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw, height=480, width=640 ! videoconvert ! x264enc tune=zerolatency ! video/x-h264, profile=high ! mpegtsmux ! srtserversink uri=srt://:12345/
(エラーは出ていないが表示もされない)
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
Redistribute latency...
^Chandling interrupt.
Interrupt: Stopping pipeline ...
Execution ended after 0:01:50.658920768
Setting pipeline to NULL ...
Freeing pipeline ...
gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw, height=480, width=640 ! videoconvert ! x264enc tune=zerolatency key-int-max=30 ! mpegtsmux ! srtserversink uri="srt://:12345" latency=500
(失敗)
gst-launch-1.0 -v filesrc location=start_up.mp4 ! qtdemux ! queue ! h264parse ! avdec_h264 ! video/x-raw, height=1080, width=1920 ! videoconvert ! x264enc tune=zerolatency ! video/x-h264, profile=high ! mpegtsmux ! srtsink uri=srt://:12345/
(失敗)
gst-launch-1.0 filesrc location=start_up.mp4 ! qtdemux ! h264parse ! rtph264pay ! udpsink host=127.0.0.1 port=5000
(失敗)
gst-launch-1.0 filesrc location=30ftp.mp4 ! qtdemux ! h264parse ! rtph264pay ! srtsink uri=srt://:12345
(失敗)
gst-launch-1.0 filesrc location=30ftp.mp4 ! qtdemux ! h264parse ! identity drop-probability=1 ! rtph264pay ! srtsink uri=srt://:12345
gst-launch-1.0 v4l2src ! video/x-raw,width=640,height=480 ! autovideosink
gst-launch-1.0 v4l2src device="/dev/video0" ! 'image/jpeg, width=1280, height=720, framerate=30/1' ! jpegdec ! nv3dsink
gst-launch-1.0 v4l2src device=/dev/video0 ! 'video/x-raw,format=(string)YUYV,width=640,height=480,framerate=30/1' ! autovideosink
gst-launch-1.0 v4l2src device=/dev/video0 ! 'video/x-raw,width=640,height=480,framerate=30/1' ! videoconvert ! autovideosink
ChatGPTが示してきた答え
gst-launch-1.0 v4l2src device=/dev/video0 ! 'video/x-raw,format=(string)YUY2,width=640,height=480,framerate=30/1' ! autovideosink
でも、これでもエラーはでてこないが、動かない。
C270nのWebカメラ映像をGstreamerで録画したい
(ChatGPTが示してきた答え)
gst-launch-1.0 v4l2src device=/dev/video0 ! 'video/x-raw,format=(string)YUY2,width=640,height=480,framerate=30/1' ! videoconvert ! x264enc ! mp4mux ! filesink location=output.mp4
で、ようやく動いたのが、これ
gst-launch-1.0 v4l2src device="/dev/video0" ! 'image/jpeg, width=1280, height=720, framerate=30/1' ! jpegdec ! autovideosink
ちょっと画面が大きいので、今、表示しているのは、以下のコマンドで少し小さくして表示
ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/Gstreamer$ gst-launch-1.0 v4l2src device="/dev/video0" ! 'image/jpeg, width=640, height=480, framerate=30/1' ! jpegdec ! autovideosink
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Got context from element 'autovideosink0': gst.gl.GLDisplay=context, gst.gl.GLDisplay=(GstGLDisplay)"\(GstGLDisplayX11\)\ gldisplayx11-0";
Setting pipeline to PLAYING ...
New clock: GstSystemClock
WARNING: from element /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstGLImageSinkBin:autovideosink0-actual-sink-glimage/GstGLImageSink:sink: A lot of buffers are being dropped.
Additional debug info:
gstbasesink.c(3003): gst_base_sink_is_too_late (): /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstGLImageSinkBin:autovideosink0-actual-sink-glimage/GstGLImageSink:sink:
There may be a timestamping problem, or this computer is too slow.
WARNING: from element /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstGLImageSinkBin:autovideosink0-actual-sink-glimage/GstGLImageSink:sink: A lot of buffers are being dropped.
Additional debug info:
gstbasesink.c(3003): gst_base_sink_is_too_late (): /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstGLImageSinkBin:autovideosink0-actual-sink-glimage/GstGLImageSink:sink:
There may be a timestamping problem, or this computer is too slow
表示されたのはいいけど、警告が凄い
ちなみに、SRTの通信にも成功してVLCで表示できました(遅延が凄いけど(2~3秒))。
gst-launch-1.0 v4l2src device="/dev/video0" ! 'image/jpeg, width=640, height=480, framerate=30/1' ! jpegdec ! videoconvert ! x264enc tune=zerolatency key-int-max=30 ! mpegtsmux ! srtserversink uri="srt://:12345" latency=500
コマンドをかたっぱしからくっつけたでけです。
再度、『wsl で USBのWebカメラを使う』に挑戦中
を経て、再度、wsl で USBのWebカメラを使うに、挑戦中。
ちなみにターゲットのカメラはこちら(ロジクール Webカメラ C270n HD 720P)です。
ちなみに前提として、https://github.com/dorssel/usbipd-win/releases から、usbipd-win_3.0.0.msiをダウンードしてWIndows10に入れています。
とりあえずWindows10(×11)の、powershell(管理者モード)で、以下を確認
PS C:\WINDOWS\system32> wsl --list --all --verbose
NAME STATE VERSION
* docker-desktop-data Stopped 2
Ubuntu-20.04 Running 2
docker-desktop Stopped 2
という、いわゆる「オール2」をなんとか実現。
PS C:\WINDOWS\system32> usbipd wsl list
BUSID VID:PID DEVICE STATE
4-1 1058:25a2 USB 大容量記憶装置 Not attached
4-2 04bb:011c USB 大容量記憶装置 Not attached
5-3 04d9:1400 USB 入力デバイス Not attached
6-1 0d8a:0103 USB 印刷サポート Not attached
6-3 093a:2510 USB 入力デバイス Not attached
7-2 04f9:02c0 USB 印刷サポート, Brother DCP-J940N, USB 大容量記憶装置 Not attached
8-1 0a12:0001 Generic Bluetooth Radio Not attached
8-2 0d8c:0139 USB PnP Sound Device, USB 入力デバイス Not attached
8-3 046d:0825 Logi C270 HD WebCam Not attached
8-4 04e6:511a SCR3310-NTTCom USB SmartCard Reader Not attached
までは、なんとか出てくるのだけど、
PS C:\WINDOWS\system32> usbipd wsl attach --busid 8-3
usbipd: info: Using default WSL distribution 'docker-desktop-data'; specify the '--distribution' option to select a different one.
usbipd: error: The selected WSL distribution is not running; keep a command prompt to the distribution open to leave it running.
このエラーが取れない(いまいましい)。
https://github.com/dorssel/usbipd-win/issues/136 のページを読んでいたら、ちょっと気になった一節があったので、これを試してみました。
PS C:\WINDOWS\system32> usbipd wsl attach --distribution Ubuntu-20.04 --busid 8-3
としたら、何も言わずに、「通し」ました。
通らない場合もありました。
usbipd: error: The service is currently not running; a reboot should fix that.
というエラーがでてきて困りました。
この場合、管理者モードで立ち上げたpowershellから、
usbipd server
を投入しつつ、別の管理者モードでpowershellから、"usbipd wsl attach --distribution Ubuntu-20.04 --busid 8-3" を実施すると上手くみたいです(powershellが2つも上がっている状態はうっとうしですが)
BUSID VID:PID DEVICE STATE
4-1 1058:25a2 USB 大容量記憶装置 Not attached
4-2 04bb:011c USB 大容量記憶装置 Not attached
5-3 04d9:1400 USB 入力デバイス Not attached
6-1 0d8a:0103 USB 印刷サポート Not attached
6-3 093a:2510 USB 入力デバイス Not attached
7-2 04f9:02c0 USB 印刷サポート, Brother DCP-J940N, USB 大容量記憶装置 Not attached
8-1 0a12:0001 Generic Bluetooth Radio Not attached
8-2 0d8c:0139 USB PnP Sound Device, USB 入力デバイス Not attached
8-3 046d:0825 Logi C270 HD WebCam Attached - Ubuntu-20.04
8-4 04e6:511a SCR3310-NTTCom USB SmartCard Reader Not attached
おお、通ったようだ ―― では、ここからどうすればいいだっけ?
WSLからlsusbを実行し、接続されているUSBデバイスをリストアップすると、ッデバイスが見えるようになっていました。
ebata@DESKTOP-P6KREM0:/dev$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 046d:0825 Logitech, Inc. Webcam C270
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
ここから先は、
WSL2 USBカメラ+他のUSB機器 2022年09月06日版
を参照。
私の環境でも、
ebata@DESKTOP-P6KREM0:/dev$ ls -l /dev/video
ls: cannot access '/dev/video': No such file or directory
となったので、Linuxカーネルをカスタムビルド に入る準備が整ったのだろう。憂鬱だ。カーネルのビルドと聞くだけで、おぞましい記憶が蘇えってくるから。
と、泣き言をいってもしかたがないので、
https://github.com/PINTO0309/wsl2_linux_kernel_usbcam_enable_conf
に突っ込むこととする。
On WSL2.
ebata@DESKTOP-P6KREM0:~$ uname -r -v
5.15.90.1-microsoft-standard-WSL2 #1 SMP Fri Jan 27 02:56:13 UTC 2023
幸い、ページの内容と同じのようだ。
On Windows Terminal.
PS C:\WINDOWS\system32> wsl --update
更新プログラムを確認しています。
Linux 用 Windows サブシステムの最新バージョンは既にインストールされています。
PS C:\WINDOWS\system32> wsl --shutdown
で、
PS C:\WINDOWS\system32> wsl --install -d Ubuntu-20.04
Ubuntu 20.04 LTS は既にインストールされています。
Ubuntu 20.04 LTS を起動しています...で、
On WSL2ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata$ uname -r -v
5.15.90.1-microsoft-standard-WSL2 #1 SMP Fri Jan 27 02:56:13 UTC 2023
で、
ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata$ sudo apt update && sudo apt upgrade -y
[sudo] password for ebata:
Hit:1 http://ppa.launchpad.net/longsleep/golang-backports/ubuntu focal InRelease
(中略)
Calculating upgrade... Done
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
で、
ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata$ sudo apt install -y build-essential flex bison libgtk-3-dev libelf-dev libncurses-dev autoconf libudev-dev libtool zip unzip v4l-utils libssl-dev python3-pip cmake git iputils-ping net-tools dwarves guvcview python-is-python3 bc
Reading package lists... Done(中略)
Processing triggers for install-info (6.7.0.dfsg.2-5) ...
Processing triggers for desktop-file-utils (0.24-1ubuntu3) ...
で、
ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata$ cd /usr/src
ebata@DESKTOP-P6KREM0:/usr/src$ TAGVERNUM=5.15.90.1 && TAGVER=linux-msft-wsl-${TAGVERNUM} && WINUSERNAME=ebata
ebata@DESKTOP-P6KREM0:/usr/src$ sudo git clone --depth 1 -b ${TAGVER} https://github.com/microsoft/WSL2-Linux-Kernel.git ${TAGVERNUM}-microsoft-standard && cd ${TAGVERNUM}-microsoft-standard
Cloning into '5.15.90.1-microsoft-standard'...(中略)
Updating files: 100% (73704/73704), done.
で、
ebata@DESKTOP-P6KREM0:/usr/src/5.15.90.1-microsoft-standard$ sudo wget -O .config https://github.com/PINTO0309/wsl2_linux_kernel_usbcam_enable_conf/raw/main/${TAGVER}/config-${WSL_DISTRO_NAME} && sudo chmod 777 .config && sudo make clean
--2023-06-08 23:52:43-- https://github.com/PINTO0309/wsl2_linux_kernel_usbcam_enable_conf/raw/main/linux-msft-wsl-5.15.90.1/config-Ubuntu-20.04
(中略)2023-06-08 23:52:44 (11.3 MB/s) - ‘.config’ saved [123800/123800]
で、ここからが、本格的なカーネルコンパイルのようで、相当時間がかかった。パスワードを1回聞かれました
ebata@DESKTOP-P6KREM0:/usr/src/5.15.90.1-microsoft-standard$ sudo make -j$(nproc) KCONFIG_CONFIG=.config && sudo make modules_install -j$(nproc) && sudo make install -j$(nproc)
SYNC include/config/auto.conf.cmd(中略)
BUILD arch/x86/boot/bzImage
Kernel: arch/x86/boot/bzImage is ready (#1)
[sudo] password for ebata:
arch/x86/Makefile:142: CONFIG_X86_X32 enabled but no binutils support(中略)
I: /boot/initrd.img is now a symlink to initrd.img-5.15.90.1-microsoft-standard-WSL2+
で、
ebata@DESKTOP-P6KREM0:/usr/src/5.15.90.1-microsoft-standard$ sudo rm /mnt/c/Users/${WINUSERNAME}/vmlinux
rm: cannot remove '/mnt/c/Users/ebata/vmlinux': No such file or directory
(ここで初めてエラーになった。で、実際に、vmlinuxがなかったので、このままにして次に進んだ)
で
ebata@DESKTOP-P6KREM0:/usr/src/5.15.90.1-microsoft-standard$ sudo cp /usr/src/${TAGVERNUM}-microsoft-standard/vmlinux /mnt/c/Users/${WINUSERNAME}/
で、
ebata@DESKTOP-P6KREM0:/usr/src/5.15.90.1-microsoft-standard$ cat << 'EOT' > /mnt/c/Users/${WINUSERNAME}/.wslconfig
> [wsl2]
> kernel=C:\\Users\\ebata\\vmlinux
> EOT
で、
On Windows Terminal. (新しいターミナルから)
PS C:\WINDOWS\system32> wsl --shutdown
On WSL2。ビルドされたカーネルが正常にロードされた場合、カーネル名の末尾に+が表示されます。#nはカーネルがビルドされた回数です。
ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata$ uname -r -v
5.15.90.1-microsoft-standard-WSL2+ #1 SMP Thu Jun 8 23:54:50 JST 2023
で、 On WSL2.で
ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata$ cd /usr/src
ebata@DESKTOP-P6KREM0:/usr/src$ TAGVERNUM=6.1.21.2
ここの6.1.21.2は、
https://github.com/microsoft/WSL2-Linux-Kernel/tags
にあった最新のものを適当に入れた(知らん)。
On WSL2.
ebata@DESKTOP-P6KREM0:/usr/src$ sudo git clone -b ${TAGVER} https://github.com/microsoft/WSL2-Linux-Kernel.git ${TAGVERNUM}-microsoft-standard && cd ${TAGVERNUM}-microsoft-standard
で、これが結構長かった。
で、
ebata@DESKTOP-P6KREM0:/usr/src/6.1.21.2-microsoft-standard$ sudo cp /proc/config.gz config.gz && sudo gunzip config.gz && sudo mv config .config
ebata@DESKTOP-P6KREM0:/usr/src/6.1.21.2-microsoft-standard$ sudo make menuconfig
HOSTCC scripts/basic/fixdep(中略)
HOSTLD scripts/kconfig/mconf
(ここで、GUIが突然登場してビビったが、"save"を選んで、".config"を選んで終了させる)
*** End of the configuration.
*** Execute 'make' to start the build or try 'make help'.
で、On Windows Terminal.で
$ wsl --shutdown
$wsl -d Ubuntu-20.04
で、
PS C:\WINDOWS\system32> usbipd wsl attach --busid 8-3
usbipd: info: Using default WSL distribution 'docker-desktop-data'; specify the '--distribution' option to select a different one.
usbipd: error: The selected WSL distribution is not running; keep a command prompt to the distribution open to leave it running.
とあいもかわらず、このエラーがでるので、
PS C:\WINDOWS\system32> usbipd wsl attach --distribution Ubuntu-20.04 --busid 8-3
で、対処。
で、WSLからどーなったか見てみる。
ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 046d:0825 Logitech, Inc. Webcam C270
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata$ ls -l /dev/video*
crw------- 1 root root 81, 0 Jun 9 00:57 /dev/video0
crw------- 1 root root 81, 1 Jun 9 00:57 /dev/video1
あ、ようやくデバイスがきた。この2行の為に、これまでの苦労があった。
で、後は、https://zenn.dev/pinto0309/articles/e1432253d29e30に記載されているpythonのプログラムをそのまま使わせて頂き、カメラから映像がでることを確認しました。
Corrupt JPEG data: 2 extraneous bytes before marker 0xd6
Corrupt JPEG data: 6 extraneous bytes before marker 0xd2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd0
Corrupt JPEG data: 2 extraneous bytes before marker 0xd0
Corrupt JPEG data: 1 extraneous bytes before marker 0xd4
Corrupt JPEG data: 2 extraneous bytes before marker 0xd3
Corrupt JPEG data: 1 extraneous bytes before marker 0xd0
Corrupt JPEG data: 11 extraneous bytes before marker 0xd3
が出てきていますが、気にしません。
ちなみに、画像が出てこなかったので、XWinrcを起動したところ、表示ができたようです。https://dev.classmethod.jp/articles/wsl-x-window/
と、/dev/videoを作るためだけに、何時間かが溶けました。
ところが、
ebata@DESKTOP-P6KREM0:/dev$ gst-launch-1.0 videotestsrc ! v4l2sink device=/dev/video0
Setting pipeline to PAUSED ...
ERROR: Pipeline doesn't want to pause.
ERROR: from element /GstPipeline:pipeline0/GstV4l2Sink:v4l2sink0: Could not open device '/dev/video0' for reading and writing.
Additional debug info:
v4l2_calls.c(621): gst_v4l2_open (): /GstPipeline:pipeline0/GstV4l2Sink:v4l2sink0:
system error: Permission denied
Setting pipeline to NULL ...
Freeing pipeline ...
って、何だ、これ?
で、やっと分かったんですが。
ebata@DESKTOP-P6KREM0:/dev$ ls -la video*
crw------- 1 root root 81, 0 Jun 9 23:35 video0
crw------- 1 root root 81, 1 Jun 9 23:35 video1
となっていて、
オープンするには
root
ユーザvideo
グループに所属
である必要があるらしいのです。
だた、どーしてもGstreamerでは表示できないのですよ
(以下に続く)
WIndows10のWSL Ubuntu-20.04に仮想の/dev/video*を作って、Webカメラ C270n をGstreamer で表示できるようにするまでの軌跡