Moiz's journal

プログラミングやFPGAなどの技術系の趣味に関するブログです

RISCVエミュレータを作り始めた

はじめに

RISCVエミュレータを作り始めました。このエントリーはそのメモです。 個人的なメモなので、読者の方の事はまだあまり考えていません。

ある程度めどがたったらもうちょっと読みやすいエントリーを書きます。

目標

(完全な車輪の再発明ですが、個人の趣味ですので。)

参考図書

リポジトリ

https://github.com/moizumi99/m99_riscv_emulator

作業

  • 「動かしてわかるCPUの作り方10講」(以下CPU10講)のエミュレータを元に、雛形を作成。

    • ターゲット言語をC++に変更。
    • 拡張に備えてファイルを分割

      • RISCV_Emulator.cc (メイン)
      • RISCV_cpu.cc (エミュレータ本体)
      • load_assembler.cc (アセンブラ・コードの作成・ロード)
      • instruction_encdec.cc (機械語を32bitにパックするためのコード)
      • bit_tools.cc (ビットの切り出し等用のユーティリティ)
      • load_assembler_test.cc (load_assembler.cc用のテスト)
    • 拡張のための変更

      • 32bit命令のために配列をshortからuint32_tに変更
      • メモリ配列を大きくして、romとramを共通化
      • レジスタを32個に拡張
      • その他いろいろ(Makefileの作成など)
  • RISC-V 命令対応への変更

最初に使用する命令の選定

まずは「動かしてわかるCPUの作り方10講」で使われている1から10まで足し合わせるアセンブリコードを再現したい。

  • 「動かしてわかるCPUの作り方10講」のCPUの命令と、RISCVの命令(RV32I)の対応
CPU10講CPU CPU10講動作 対応するRISC-V命令
mov RegA <- RegB add rd, rs1, zeroで代用。(zeroはゼロレジスタ)
add RegA <- RegA + RegB add rd, rs1, rs2 (x[rd] <- x[rs1] + x[rs2])
ldl RegA(Low) <- Data (8bit) addi rd, zero, immediate (x[rd] <- zero + immeidate)で代用
ldh RegA(High) <- Data (8bit) 今回はスキップ。必要ならlui (Load Upper Immediateを実装)
cmp flag <- (RegA == RegB) 今回はスキップ(次のbeqで代用)
je pc <- Addr if flag==1 beq rs1, rs2, offset (pc += offset if rs1 == rs2)で代用
jmp pc <- Addr jal x0, offset (pc += offset)
ld RegA <- M[Addr] 今回はスキップ(レジスタを使うので)
st M[Addr] <- RegA 今回はスキップ(レジスタを使うので)
hlt 停止 ret (実体はjalr x0, x1, 0)で代用。x1は戻りアドレス

とりあえず、このエミュレータはret命令で停止するものとします。

それぞれの命令のラベルとタイプ、ファンクションのリストです。

命令 タイプ ラベル funct7 or 6 funct3
add R 0110011 0000000 000
addi I 0010011 NA 000
sub R 0110011 0100000 000
and R 0110011 0000000 111
or R 0110011 0000000 110
slli I 0010011 000000 001
srli I 0010011 000000 101
srai I 0010011 010000 101
beq B 1100011 NA 000
jal J 1101111 NA NA
jalr I 1100111 NA NA

funct6という名称は実際にはありませんが、immediateの上位6ビットが固定になっている部分を便宜上このように表記しました。

アセンブリコードの変更

まずは「動かしてわかるCPUの作り方10講」のサンプルコードを変換してみます。

# t0: カウンタ(初期値0)
addi t0, zero, 0
# t1; 和(初期値0)
addi t1, zero, 0
# t2: 上限(10)
addi t2, zero, 10
# ループ先頭
# t0 = t0 + 1
addi t0, t0, 1
# t1 = t1 + t0
add t1, t1, t0
# t0 = t2 なら+ 8ジャンプ
beq t0, t2, 8
# -16 (4命令バック)ジャンプ
jal x0, -16
# A0 (返り値を保存するレジスタに結果を移動)
add a0, t1, x0
# リターン(a0は戻り値)
jalr x0, ra, 0

命令のエンコーダー

まずはCPUに渡すバイナリを作る必要があります。

RISC-V原典を眺めながら、各命令のopcode、funct3、funct7、レジスタ番号、即値を32bitに埋め込んでいくコードを書きます。

RISC-V(RV32I)の命令は次の6つのタイプにわかれます。

  • R-type
  • I-type
  • S-type
  • B-type
  • U-type
  • J-type

それぞれフォーマットが異なり、タイプごとに引数の種類も異なります。

そこで必要な命令毎に

  1. タイプを判断しフォーマットを選択
  2. opcodeとfunct3、funct7を32bit内に埋め込む
  3. 必要な引数(rd, rs1, rs2, immediate )を判断
  4. 引数の情報を32bit内の指定された位置に埋め込む

というコードを書きます。

RISC-Vでは、何故か一部の即値のビット位置が入れ替わっていて、これを入れ替えるのが大変でした。C/C++でのビット演算に苦労していると、こんなアドバイスをいただきました。

喜んで使わせていただきます。これでいちいちマスクする苦労から開放されました。

ビットフィールドを使って、それぞれの要素(レジスタ番号、即値、opcode等)をクラスメンバーとして定義します。

例えばこんな感じです。

class bitfield {
  public:
    virtual uint32_t value() { return 0; };
    virtual void set_value(uint32_t value) {};

    uint8_t opcode: 7;
    uint8_t rd: 5;
    uint8_t rs2: 5;
    uint8_t rs1: 5;
    uint8_t funct3: 3;
};

class r_type : public bitfield {
  public:
    uint8_t funct7: 7;
    uint32_t value();
    void set_value(uint32_t value);
};

最初はunionとstructを使って、こんな感じで書いていたのですが、

union r_type {
    uint32_t value;
    struct {
        uint8_t funct7 : 7;
        uint8_t rs2 : 5;
        uint8_t rs1 : 5;
        uint8_t funct3 : 3;
        uint8_t rd : 5;
        uint8_t opcode : 7;
    };
};

パッキングやパディングが不安なのでとりあえずクラスにしています。 アトリビュートを使ってうまくいくようならこの方法にもどそうと思います。

機械語を生成する部分は、CPU10講にならって決め打ちのバイナリを生成するコードを書きました。

void load_assembler(uint32_t *mem) {
  mem[0] = asm_addi(T0, ZERO, 0);
  mem[1] = asm_addi(T1, ZERO, 0);
  mem[2] = asm_addi(T2, ZERO, 10);
  mem[3] = asm_addi(T0, T0, 1);
  mem[4] = asm_add(T1, T1, T0);
  mem[5] = asm_beq(T0, T2, 8);
  mem[6] = asm_jal(ZERO, -16);
  mem[7] = asm_add(A0, T1, ZERO);
  mem[8] = asm_jalr(ZERO, RA, 0);
}

これで実行対象機械語コードが用意できました。次はいよいよCPUエミュレータ側のコードです。

命令のデコード

命令のデコードはCPU10講の内容を参考に、RISC-V用に次の用なものにしました。

  1. 下7bitのオペコード(opcode)を読み込む
  2. 必要があれば、14:12ビットのfunct3を読み込む
  3. 必要があれば、31:25ビットのfunct7を読み込む(今回は未実装)
  4. opcode、funct3とfunct7から命令の種類を判定
  5. 必要に応じてrd(ディスティネーションレジスタ)、rs1(対象レジスタ1)、rs2(対象レジスタ2)をデコード
  6. 必要に応じて即値(12bit, 13bit, 21bit, 24bitの4種類がある)をデコード

さきほどシャッフルした即値のビットを戻す作業が面倒ですが、それ以外は単に対応する位置にあるビットを切り出すだけです。

命令の実行

今回選んだ命令に関しては、命令の実行はCPU10講と似た形式です。大きな違いは

  • 命令種類が減った
  • ゼロ番目のレジスタはゼロレジスタ
  • ジャンプが相対ジャンプになった
  • ret命令で動作終了

程度です

その他

実は今回一番複雑だったのは機械語を作成する部分、次がデコーダーです。複雑なので最初からテストを(割と)ちゃんと書きました。 各アセンブラの命令毎に、2〜3の命令例が正しいバイナリになっているか、またバイナリが正しくデコードされているのかを確認しました。コードはload_assembler_test.ccにあります。実は今回一番時間がかかっている部分かもしれません。

ファイルが増えたのでMakefileを作成しておきました。

実行結果

では実行してみます。

$ ./RISCV_Emulator 
Assembler set.
Execution start
   PC    Binary     T0     T1     T2     T3     A0
    0  00000293      0      0      0      0      0
    4  00000313      0      0      0      0      0
    8  00a00393      0      0      0      0      0
   12  00128293      0      0     10      0      0
   16  00530333      1      0     10      0      0
   20  00728463      1      1     10      0      0
   24  ff1ff06f      1      1     10      0      0
    8  00a00393      1      1     10      0      0
   12  00128293      1      1     10      0      0
   16  00530333      2      1     10      0      0
   20  00728463      2      3     10      0      0
   24  ff1ff06f      2      3     10      0      0
    8  00a00393      2      3     10      0      0
   12  00128293      2      3     10      0      0
   16  00530333      3      3     10      0      0
   20  00728463      3      6     10      0      0
   24  ff1ff06f      3      6     10      0      0
    8  00a00393      3      6     10      0      0
   12  00128293      3      6     10      0      0
   16  00530333      4      6     10      0      0
   20  00728463      4     10     10      0      0
   24  ff1ff06f      4     10     10      0      0
    8  00a00393      4     10     10      0      0
   12  00128293      4     10     10      0      0
   16  00530333      5     10     10      0      0
   20  00728463      5     15     10      0      0
   24  ff1ff06f      5     15     10      0      0
    8  00a00393      5     15     10      0      0
   12  00128293      5     15     10      0      0
   16  00530333      6     15     10      0      0
   20  00728463      6     21     10      0      0
   24  ff1ff06f      6     21     10      0      0
    8  00a00393      6     21     10      0      0
   12  00128293      6     21     10      0      0
   16  00530333      7     21     10      0      0
   20  00728463      7     28     10      0      0
   24  ff1ff06f      7     28     10      0      0
    8  00a00393      7     28     10      0      0
   12  00128293      7     28     10      0      0
   16  00530333      8     28     10      0      0
   20  00728463      8     36     10      0      0
   24  ff1ff06f      8     36     10      0      0
    8  00a00393      8     36     10      0      0
   12  00128293      8     36     10      0      0
   16  00530333      9     36     10      0      0
   20  00728463      9     45     10      0      0
   24  ff1ff06f      9     45     10      0      0
    8  00a00393      9     45     10      0      0
   12  00128293      9     45     10      0      0
   16  00530333     10     45     10      0      0
   20  00728463     10     55     10      0      0
   28  00030533     10     55     10      0      0
   32  00008067     10     55     10      0     55
Return value: 55

実行できました!

今後の課題

次のステップですが、

  • テスト用コードのリファクタリング(今は手作業なので命令が増えると大変)
  • ロードストア等、対応する命令を増やす
  • メモリ領域を増やす
  • 外部プログラムファイルの読み込み(できればelf形式で)

というあたりを考えています。

最終目標はFPGAで動作するCPUをRTLで書くことなのですが、これは年単位の目標です。

【技術書典6】Colabから印刷所に出せる原稿を作るワークフロー

Colabから印刷所に出せる原稿を作るワークフロー

はじめに

先日行われた技術書典6で「PythonとColabでつくる-ゼロから作るRAW現像」をid:uchan_nosさんのブースで頒布していただき、用意していた全100部を完売することができました。 ひと月前に部数を相談していたときには50部売れるかなと心配していたのが嘘のようです。 id:uchan_nosさんと@akachochinさんにはいくら感謝しても足りません。

さてイベントも終わり一段落したところですが、今回の原稿作成はちょっと変わったワークフローだったのでまとめておこうかと思います。

Colabから原稿へ移す際の問題点

今回の本はタイトルからもわかるとおり、Colab上で実行できるコードを使う事により、読者のハードルを下げるというのが特徴の一つです。 書籍の方ではColabで行った処理を、結果含めてそのまま再現しなくてはなりません。

当然コードは全部実行可能、出力結果はColabの物と同一でなくてはなりませんが、これが意外と問題になります。

もともとこの同人誌は当ブログで書いた連続記事が元になっています。ブログの方ではJupyter Notebookを使いましたが、実行可能なコードと解説という組み合わせは同人誌版とほぼ同じです。 しかしブログ版を書いたときにはコードはJupyterからのコピペに頼っていたために、

  • コピーミス
  • バージョンが違うコードが混在する
  • 後からの編集で原稿とのミスマッチがおきる

という問題がおきました。特に最初の2つはコードの実行ができなくなる可能性があるので大問題です。

また今回は終盤結構な数の数式が出てくるので、編集の手間を考えるとできるだけ手戻りは防ぎたいところです。

Colabから原稿へのワークフロー

そこで今回はこのようなワークフローを選択しました。

  1. ブラウザ上でColabでプログラム作成。GitHubに保存。
  2. 同Colabで原稿作成(図およびLaTex形式の数式入り)。GitHubに保存。
  3. ローカル環境で、nbconvertによりColabのノートブックからPDFに変換。
  4. 一次校正
  5. nbconvertによりColabからマークダウン形式への変換
  6. 自作スクリプトPython)による画像リンクの修正
  7. マークダウンからPDFに変換
  8. 二次校正
  9. md2reviewでMark DownからRe:VIEW形式に変換
  10. 壊れてしまったLaTex形式数式を修正
  11. レイアウトの調整
  12. Re:VIEWによるPDF原稿の出力
  13. 最終校正
  14. GitHub上の原稿の調整(公開するため)
  15. 完成

また各ステップでMakefileをつくり、できるだけ単純作業は自動化するようにしました。 具体的にはColabで変更を加えると、Make一発で9のRe:VIEW形式への変換まで実行されるようにしました。

ここで4の校正は数回、8のニ時校正も2〜3回行っていますが、Colabで変更してから校正用PDFにするまでは自動なので負担はそれほど大きくありませんでした。

一次と二次の校正の回数が多いのは、Re:VIEW形式にしたあとでは手作業が多いため、これ以降はColabには戻りたくないので、事前にできるだけ完成度を上げておく必用があったからです。

解説と振り返り

最初の目論見では、3のPDFの完成度が高いようならそのまま本にしてしまおうと思っていたのですが、実際に出力されたPDFは間延びしたもので、また、印刷原稿に必用なトンボやノンブルもなく、印刷所にだす原稿には使えなさそうなクオリティーでした。ただ、テキストやColabのコードの確認には十分だったので何回かPDF化してその上で校正しました。

次の5のマークダウン形式への変換と7のPDFの変換では、GitHub上に用意した画像ファイルがPDF化されないという問題がありました。これは6にて、ローカルのリポジトリーのパスに置き換えるスクリプトを実行することで回避しました。

9の「壊れてしまったLaTex形式数式」の修正というのは、md2reviewがうまく認識できなかったLaTex数式を通常のマークダウンと認識してしまう部分が何箇所かあったので、それを修正する作業です。これは自動化したかったのですがうまくいきませんでした。また、md2reviewの調整でうまくいくのかもしれません。1

10以降は通常のRe:VIEWによる技術書執筆とあまり変わらないと思います。今回このあたりは基本的に手作業でした。23

原稿ができたあとでみてみると、Colabノートブックから、マークダウン形式、Re:VIEW形式、と2段階の返還をしているのが気になります。 nbconvertはLaTex形式への変換もできるので、そうしておけば1回の変換ですんだのではないかと思いますが、私自信がLaTexについてあまり知らないのでこのようなフローになってしまいました。

また、ステップ10以降が手作業がメインになってしまっている点も気になります。理想はColabから最終Re:VIEWへ完全自動化だったのですが、なかなかそううまくは行かないようです。 このあたりは次回への課題です。

環境に関しては、今回は原稿部分は図の作成含めてすべてUbuntu18.04上で行いました。表紙の作成はWindows上で行っています。

校正には印刷の他にiPad Proを使用しましたが非常に便利でした。

まとめ

以上、今回「ゼロから作るRAW現像」の原稿を作成するにあたって利用したワークフローを紹介しました。

ColabやJupyterといったPythonインタラクティブノートブックで実行したものを原稿にする際にしか参考にならないニッチな情報ですが、もともと技術書典というのはそういうニッチな物を扱う点に価値があるのかもしれませんので、ここで関連記事として公開させていただきます。

最後に

【技術書典6】で頒布した「PythonとColabでできる - ゼロから作るRAW現像」の書籍版・PDF版ををBOOTHにて販売しています。 書籍版は4/16/2019現在入荷作業中ですが、特典のPDF版は購入後商品ページからすぐにダウンロードできます。

moiz.booth.pm

【技術書典6】キヤノンD70のRAW画像のPythonによる現像

キヤノンD70のRAW画像のPythonによる現像

このページについて

このページでは「技術書典6」にて配布する「PythonとColabでできる - ゼロからできるRAW現像」のデモとして、書籍ではあつわかないキヤノンのRAWファイルの現像を行ってみます。

あくまでデモという目的なのでパラメータは最適化していませんし、一部機能はオフにしています。

このデモの内容をColabで実際に実行するには次のリンクからアクセスしてみて下さい。

colab.research.google.com

準備

まずライブラリーのインストールと、モジュールのインポート、画像の読み込みを行います。内容については書籍を参照ください。

# rawpyとimageioのインストール
!pip install rawpy;
!pip install imageio;

# rawpy, imageio, numpuy, pyplot, imshowのインポート
import rawpy, imageio
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow

# 前節までに作成したモジュールのダウンロードとインポート
!if [ ! -f raw_process.py ]; then wget https://github.com/moizumi99/camera_raw_processing/raw/master/raw_process.py; fi
from raw_process import simple_demosaic, white_balance, black_level_correction, gamma_correction
from raw_process import demosaic, defect_correction, color_correction_matrix, lens_shading_correction
from raw_process import noise_filter, apply_matrix, edge_enhancement, tone_curve_correction, advanced_demosaic

# 日本語フォントの設定
!apt -y install fonts-ipafont-gothic
plt.rcParams['font.family'] = 'IPAPGothic'

日本語が文字化けしている場合は、以下のセルから冒頭の#を削除した上で実行して、Rntime->Restart Runtimeを選択し、その後ページはじめから実行してみて下さい。

# もし日本語が文字化けしている場合以下の3行の行頭の#を削除して実行後、
#import matplotlib
#target_dir = matplotlib.get_cachedir()
#! rm {target_dir}/*.json
# その後Runtime->Restart Runtime選択してページ全体を再実行

今回はフリーのRAWファイルサンプルを公開しているRAWSMAPLES.CHからデータをダウンロードします。

使うのはCANON EOS70D のデータで、ファイル名はRAW_CANON_EOS70D.CR2です。

# 画像をダウンロードします。
! wget http://www.rawsamples.ch/raws/canon/RAW_CANON_EOS70D.CR2

自分で撮影した画像を使用する場合は以下のセルからコメントを取り除きアップロードします。

#from google.colab import files
#uploaded = files.upload()
# RAWファイルの名前。
# アップロードしたファイルを使う場合はその名前に変更。
raw_file  = "RAW_CANON_EOS70D.CR2"
raw = rawpy.imread(raw_file)

exiftoolを使ってRAWファイルの情報を見てみましょう。

! apt install exiftool
! exiftool RAW_CANON_EOS70D.CR2
ExifTool Version Number         : 10.80
File Name                       : RAW_CANON_EOS70D.CR2
Directory                       : .
File Size                       : 23 MB
File Modification Date/Time     : 2019:04:07 15:52:05+00:00
File Access Date/Time           : 2019:04:07 15:52:33+00:00
File Inode Change Date/Time     : 2019:04:07 15:52:05+00:00
File Permissions                : rw-r--r--
File Type                       : CR2
File Type Extension             : cr2
MIME Type                       : image/x-canon-cr2
Exif Byte Order                 : Little-endian (Intel, II)
Image Width                     : 5472
Image Height                    : 3648
Bits Per Sample                 : 8 8 8

 以下略

沢山の情報が得られます。

まず、ブラックレベルは2049です。

Per Channel Black Level : 2049 2049 2049 2049

また、次の行からホワイトレベル(白をしめす基準値)11765と思われます。

Normal White Level : 11765

Bayerのパターンは「赤・緑」「緑・青」のようです。

CR2 CFA Pattern : [Red,Green][Green,Blue]

残念ながらカラーマトリクスの値がわかりません。もしかするとこのカメラでは単純なカラーマトリクスではない方式で色補正を行っているのかもしれません。 今回は適当な値を設定して使う事にします。

まずはRAWPYの機能を使って最終的な画像を見ておきましょう。

# RAWPYの機能で現像処理。
# use_camera_wbはホワイトバランスにカメラの値を使う指定。
rgb = raw.postprocess(use_camera_wb=True)
plt.title("RAWPYによる現像")
plt.imshow(rgb)
plt.axis('off')
plt.show()

f:id:uzusayuu:20190408035709p:plain

これは、鳥の餌かなにかでしょうか?

ちょっと面食らいましたが気を取り直して、RAWデータの情報を見てみましょう。

print(raw.sizes)
ImageSizes(raw_height=3708, raw_width=5568, height=3670, width=5496, top_margin=38, left_margin=72, iheight=3670, iwidth=5496, pixel_aspect=1.0, flip=6)

画像サイズは5568x3670のようです。約20Mです。

Bayerパターンを確認しましょう。

print(raw.raw_pattern)
[[0 1]
 [1 2]]

左上が赤、右下が青、というそれ以外が緑というパターンで、先程確認したEXIFの情報と一致しています。

ホワイトバランスを確認します。

print(raw.camera_whitebalance)
[2036.0, 1024.0, 1739.0, 1024.0]

これはEXIFの「WB RGGB Levels As Shot」に対応しているようです。

それではRAW現像に入りましょう。

RAW画像データをNumpy配列に読み込みます。

raw_array = raw.raw_image
h, w = raw_array.shape

それでは処理を行いましょう。

今回はデモなのでシェーディング補正や欠陥画素補正、ノイズリダクション、トーンカーブ処理は省略しています。

EXIFでわからなかったカラーマトリクスの値として(1.5, -0.25, -0.25, -0.25, 1.5, -0.25, -0.25, -0.25, 1.5)という物を仮の値としていれています。

また、ホワイトレベルで正規化した場合暗い画像になってしまうので、x2のデジタルゲインを与える事にしました。

処理の詳細については技術書典6で配布する書籍「PythonとColabでできる - ゼロからできるRAW現像」をご覧ください。

blc, pattern = raw.black_level_per_channel, raw.raw_pattern
blc_raw = black_level_correction(raw_array, blc, pattern)
gains, colors = raw.camera_whitebalance, raw.raw_colors
wb_raw = white_balance(blc_raw, gains, colors)
dms_img = advanced_demosaic(wb_raw, pattern)
# カラーマトリクス。EXIFから得られたもの。
color_matrix = np.array(
    [1.5, -0.25, -0.25, -0.25, 1.5, -0.25, -0.25, 0.25, 1.5])
ccm_img = color_correction_matrix(dms_img, color_matrix)
# ホワイトレベル。EXIFから得られた値。
white_level = 11765.0
# デジタルゲイン
digital_gain = 2
gmm_img = gamma_correction(ccm_img / white_level * digital_gain, 2.2)
sigma, edge_intensity = 2, 0.25
shp_img = edge_enhancement(gmm_img, sigma, edge_intensity)

表示してみます。

# 最終画像表示
plt.figure(figsize=(8, 8))
plt.imshow(shp_img)
plt.axis('off')
plt.title(u"最終画像")
plt.show()

f:id:uzusayuu:20190408035610p:plain

先程のRAWPYによる現像と似た画像が得られました。

今回はパラメータを簡易的なものにしたので色合いがことなる、コントラストが違う、などの点がみられます。

このあたりはカラーマトリクスの値の変更、トーンカーブ処理などで改善できると思われます。

まとめ

今回は技術書典6で配布する書籍「PythonとColabでできる-ゼロから作るRAW現像」のデモとして、キヤノンのカメラEOS70DのRAW画像ファイルを現像してみました。

f:id:uzusayuu:20190331124210j:plain:w200

書籍ではRAW画像とは何か?という疑問に答えるところから始まり、各ステップで行われる処理を基本的なところから説明し、実際に実行可能なコードを使って処理を行ってみます。

技術書典について

公式ウェブページによる紹介は以下の通りです。

新しい技術に出会えるお祭りです。

技術書典は、いろんな技術の普及を手伝いたいとの想いではじまりました。

技術書を中心として出展者はノウハウを詰め込み、来場者はこの場にしかないおもしろい技術書をさがし求める、技術に関わる人のための場として『技術書典』を開催します。

  • 日時: 2019/04/14 (日) 11:00〜17:00 (一般参加は11時~13時のみ有料)
  • 開催場所: 池袋サンシャインシティ2F 展示ホールD(文化会館ビル2F)

配布情報

  • ブース: う38「bitnos
  • 書名:「PythonとColabでできる-ゼロから作るRAW現像」
  • フォーマット
    • 書籍版:164ページ(内12ページフルカラー+表紙含む)、予価2000円
    • PDF版:フルカラー164ページ(表紙含む)、予価1000円

書籍版の方はカラーページを含むために若干高めになってしまいましたので、特典としてPDF版ダウンロード権を添付します。

またPDF版は、同等品をイベント後BOOTHでの販売を予定しています(値段など変わる可能性があります)。

サークルbitnosについて

「う38」のサークルbitnosは低レイヤーを中心としたソフトウェアのサークルです。

今回は新刊「Local APICタイマー入門」を配布します。 以下、著者の@uchan_nosさんによる紹介です。

現代のPCにはいくつものタイマーが搭載されています。本書は現代のPCタイマーの主役であるLocal APICタイマーを中心にしつつも、ACPI PMタイマー、TSCUEFI RTCの使い方も紹介します。また、x86-64における割り込みの設定についても詳しく解説します。

他に以下の既巻も頒布します。

  • Linuxカーネルモジュール自作入門」
  • システムプログラミングハンドブック」
  • 「USB 3.0 ホストドライバ自作入門」
  • C++でできる!OS自作入門」

【技術書典6】 画像処理は低レイヤー

画像処理は低レイヤー

はじめに

前回の記事で告知したとおり、4月14日に行われる技術書オンリーイベント『技術書典6』にて『う38』のサークルbitnosのご厚意で「PythonとColabでできる - ゼロから作るRAW現像」を配布します。

サークルbitnosは低レイヤーを中心とするソフトウェアのサークルなのですが、そこで画像処理の書籍を配布することに意外に思われる方もいらっしゃるかもしれません。 実際に今回配布するに至った理由の多くはサークル主のid:uchan_nosさんのご好意という面が大きいのですが、ジャンルだけをとっても実は私にはあまり違和感はありません。

RAW現像の処理はカメラ画像処理

確かにPC上で実行する市販のRAW現像ソフトを思い浮かべると、そういった処理は低レイヤーとは程遠いと言えますが、RAW現像で行われる処理はもともとカメラ内で行われていた画像処理です。

もちろんPCで行うためにより高度な処理が行える、マニュアル的な補正ができる、カメラメーカー以外が提供するソフトウェアが使える、といった違いはありますが、処理の内容的にはカメラ画像処理のエミュレーションという言い方もできると思います。

スマートフォンのカメラ機能

それではカメラ内の画像処理の例として、身近なスマートフォンのカメラ機能を考えてみましょう。

まず画像処理については次の方法が考えられます。

  1. CPU・GPUなどの汎用プロセッサで行う
  2. DSPなどの画像処理に特化した専用プロセッサで行う
  3. 専用のハードウェア回路で行う

1や2の場合は、画像処理自体はファームウェアまたはドライバーとして書かれます。

3の場合は画像処理はハードウェアの一部なのでCPUやGPUと同じレイヤーです。 ただし、制御処理や画像処理の一部はドライバーソフトウェアとして提供される事になります。

カメラ機能を実現するには他に、

などが必用です。

カメラコントロールは各種プロセッサ上で実行されますが、これはドライバーの領分です。

後処理はどこで行われるかシステムによって違いますが、GPUDSPで行う場合はファームウェアやドライバー上で行うことになります。

エンコードは専用ハードウェアやアクセラレータで行われることが多いですが、この場合画像処理部分と同様にハードウェア・ファームウェア・ドライバーといった低レイヤーで実現されます。

このように、スマートフォンのカメラ機能のほとんどの部分は低レイヤー・ソフトウェアおよび更に下の層であるハードウェアで実現されています。

そんなわけで、RAW現像は低レイヤーソフトウェアやハードウェアと関連が非常に深いのです。

最後に

とうとう技術書典6も1週間後の4月14日にせまってきました。

都合のつく方はどうぞご来場して、もし気が向いたらぜひサークルbitnosをお訪ね下さい。

技術書展の開催情報

  • 日時: 2019/04/14 (日) 11:00〜17:00 (一般参加は11時~13時のみ有料)
  • 開催場所: 池袋サンシャインシティ2F 展示ホールD(文化会館ビル2F)

書籍配布情報

  • ブース: 「う38」
  • 書名:「PythonとColabでできる-ゼロから作るRAW現像」
  • フォーマット
    • 書籍版:164ページ(内12ページフルカラー+表紙含む)、予価2000円
    • PDF版:フルカラー164ページ(表紙含む)、予価1000円

サークル情報

  • サークル: bitnos
  • サークル主催:id:uchan_nosさん
  • ジャンル: オペレーティングシステムを自作する際の要素技術の解説本など
  • 新刊書籍: 「Local APICタイマー入門」
    • 現代のPCに搭載されている様々なタイマーの使い方を紹介します

f:id:uzusayuu:20190331124210j:plain:w300


  1. オートホワイトバランス、オート露出、オートフォーカス

【技術書典6】「PythonとColabでできる-ゼロから作るRAW現像」を出します(書籍版/ダウンロード版)

はじめに

第六回目を迎える 技術書オンリーイベント 「技術書典6」にて『う38』のサークルbitnosにて「PythonとColabでできる-ゼロから作るRAW現像」(以下「ゼロから作るRAW現像」)を配布します。

f:id:uzusayuu:20190331124210j:plain:w300

技術書典について

公式ウェブページによる紹介は以下の通りです。

新しい技術に出会えるお祭りです。

技術書典は、いろんな技術の普及を手伝いたいとの想いではじまりました。

技術書を中心として出展者はノウハウを詰め込み、来場者はこの場にしかないおもしろい技術書をさがし求める、技術に関わる人のための場として『技術書典』を開催します。

  • 日時: 2019/04/14 (日) 11:00〜17:00 (一般参加は11時~13時のみ有料)
  • 開催場所: 池袋サンシャインシティ2F 展示ホールD(文化会館ビル2F)

配布情報

  • ブース: う38「bitnos
  • 書名:「PythonとColabでできる-ゼロから作るRAW現像」
  • フォーマット
    • 書籍版:164ページ(内12ページフルカラー+表紙含む)、予価2000円
    • PDF版:フルカラー152ページ(表紙含む)、予価1000円

書籍版の方はカラーページを含むために若干高めになってしまいましたので、特典としてPDF版ダウンロード権を添付します。

サークルbitnosについて

「う38」のサークルbitnosは低レイヤーを中心としたソフトウェアのサークルです。

今回は新刊「Local APICタイマー入門」を配布します。 以下、著者の@uchan_nosさんによる紹介です。

現代のPCにはいくつものタイマーが搭載されています。本書は現代のPCタイマーの主役であるLocal APICタイマーを中心にしつつも、ACPI PMタイマー、TSCUEFI RTCの使い方も紹介します。また、x86-64における割り込みの設定についても詳しく解説します。

他に以下の既巻も頒布します。

  • Linuxカーネルモジュール自作入門」
  • システムプログラミングハンドブック」
  • 「USB 3.0 ホストドライバ自作入門」
  • C++でできる!OS自作入門」

配布する本について

本書「ゼロから作るRAW現像」ではカメラのRAW画像現像処理をスクラッチから作成・解説します。 PythonとColabを使うので読者はブラウザだけで、Bayerデータからフルカラー画像までのカメラ画像処理を低レベルから理解し実行することができます。

内容的にはこのブログで以前書いた「ゼロから作るRAW現像」を大きく再構成してわかりやすくし、実行環境を設定のいらないColabに移したものです。 ブログでは説明が足りないところ飛んでいるところ多数ありましたが、そういった点を大きく改善しました。

目次

  • はじめに

    • この本について
    • 環境について
    • 書籍の内容について
  • 第 1 章 カメラ画像処理について

    • カメラ画像処理について
  • 第2章 基本的な処理

    • 2.1 準備
    • 2.2 簡易デモザイク処理
    • 2.3 ホワイトバランス補正
    • 2.4 ブラックレベル補正
    • 2.5 ガンマ補正
  • 第3章 重要な処理

    • 3.1 この章について
    • 3.2 線形補間デモザイク
    • 3.3 欠陥画素補正
    • 3.4 カラーマトリクス補正
    • 3.5 シェーディング補正
  • 第4章 画質を良くする処理

    • 4.1 この章について
    • 4.2 ノイズフィルター
    • 4.3 エッジ強調
    • 4.4 トーンカーブ補正
  • 第 5 章 応用編

    • 5.1 線形補間デモザイクの周波数特性
    • 5.2 高度なデモザイク処理
    • 5.3 ミラーレスカメラ(ソニーα 7-III) の RAW 現像
  • 付録 A

    • A.1 Colaboratory の簡単な使い方
    • A.2 RAW 画像の撮影方法
  • あとがき

付録は書籍版ではURLからのダウンロード方式になります。

内容プレビュー

以下、書籍からの抜粋です。購入検討のご参考にどうぞ。

f:id:uzusayuu:20190331124640p:plain:w150 f:id:uzusayuu:20190331124956p:plain:w150 f:id:uzusayuu:20190331132726p:plain:w150 f:id:uzusayuu:20190331132442p:plain:w150

ダウンロード頒布

イベントの雰囲気は何物にも代えがたいものですが一日限定イベントという事で当日来場できない方も多いかと思います。 私自身、海外在住の身のため過去五回の技術書展は参加できずはがゆい思いをしました。

そこで当日会場にいらっしゃることのできない方のために後日以下のURLでダウンロード頒布を開始する予定です。

https://moiz.booth.pm

販売開始はイベント当日夜以降の予定です。

最後に

委託頒布を快く引き受けてくださった@uchan_nosさんに改めて感謝します。