背景除去アプリを作る⑤|5スライダー後処理+消去/復元ブラシ+20段Undoで「自動9割・手で1割」を仕上げる【背景除去Studio制作】

アプリの作り方

背景除去アプリを作る⑤|5スライダー後処理+消去/復元ブラシ+20段Undoで「自動9割・手で1割」を仕上げる【背景除去Studio制作】

AIに投げたら、被写体の9割は一発で抜けた。だが残りの1割が言うことを聞かない。髪の先が背景に溶け、耳の穴だけ透けすぎ、腕の脇に背景の緑がひと筋残る。この「あと少し」を手で直したい人に向けた回だ。完全自動の精度をどこまでも追うより、後処理スライダーとブラシ修正を別レイヤーで持たせて、AIの出力に人の手を1割だけ足す。この記事では、5本のスライダーによる後処理、消去/復元ブラシ、20段のUndo、そして3種類の表示切替を、実際のソースコードから組み立てていく。

▶ この連載の全体像と完成アプリの使い分けガイドは連載ハブ(背景除去アプリの作り方)から。AIが9割抜いた後の「残り1割」を人の手に返す設計の回だ。

目次
  1. この連載で作るもの(全7回の地図)
  2. 第5回のゴール
  3. Step 1. 5本のスライダーで生マスクを整える
  4. Step 2. ブラシは結果に直接描かず、別レイヤーへ塗る
  5. Step 3. 合成の優先順位:消去 > 復元 > ベース
  6. Step 4. 20段のUndo:空振りクリックでスタックを汚さない
  7. Step 5. 表示切替3種と、チェッカー背景のキャッシュ
  8. 設計Q&A:ブラシとレイヤーの疑問
  9. まとめ:第5回の要点

この連載で作るもの(全7回の地図)

  1. ① 土台と全体設計 — PyQt6と3枚の純関数レイヤ
  2. ② 古典CVエンジン — FloodFill・クロマキー・Color-to-Alpha
  3. ③ 2つの難所 — 囲まれた背景ポケットとアイコンの穴
  4. ④ AIをローカルで動かす — ONNX+BiRefNetとDirectMLフォールバック
  5. ⑤ 仕上げ — 5スライダー後処理・ブラシ・20段Undo(この記事)
  6. ⑥ UI/UX — ズーム・スポイト・非同期・D&D一括処理
  7. ⑦ 完結 — 品質を数値で担保して配布する

第5回のゴール

第4回までで、古典CVとAIが吐く「ベースマスク」(uint8のアルファ、255=被写体/0=背景)が手に入った。第5回はその生マスクを仕上げの3工程に通す。postprocess_mask でしきい値やぼかしを整え、compose_final_alpha でブラシの手直しと元画像の既存アルファを合成し、update_preview で完成画像・マスク表示・背景検出の3ビューに描き分ける。読み終えるころには、AIが抜いた9割の上に、スライダーとブラシで残り1割を乗せる一本道が動いている状態になる。

設計の判断はひとつだ。エンジン(AIや古典CV)の出力を直接いじって完璧にしようとはしない。ベースマスクは触らず読み取り専用のまま置き、後処理とブラシ修正をそれぞれ独立したレイヤーとして上に重ねる。こうすると「AIをかけ直す」「しきい値を動かす」「ブラシで塗る」がお互いを壊さずに共存できる。まずは後処理スライダーから見ていく。

Step 1. 5本のスライダーで生マスクを整える

後処理は mask_pipeline.py の純関数 postprocess_mask(mask, threshold, softness, edge_shift, noise, blur) にまとまっている。UIの5スライダーがそのまま5引数になる。入力も出力もuint8のアルファマスクだけで、画像本体やUIの状態を一切知らない。だから単体でテストできるし、AIマスクにも古典CVマスクにも同じ関数を通せる。

# mask_pipeline.py
def postprocess_mask(mask, threshold, softness, edge_shift, noise, blur):
    m = mask.astype(np.float32)

    # (1) しきい値/ソフト幅: threshold を中心としたレベル補正
    # softness が小さいときは完全2値化(除算式だと境界画素が中間値になるため)
    half_width = softness / 100.0 * 127.0
    if half_width < 1.0:
        m = np.where(m >= threshold, 255.0, 0.0)
    else:
        m = (m - (threshold - half_width)) / (2.0 * half_width) * 255.0
    m = np.clip(m, 0, 255).astype(np.uint8)

最初の threshold はマスクの境界の中心をどこに置くかを決める。AIのsoft maskは境界がグレーのグラデーションで出る。半透明の帯を「ここから内側は被写体」と切る位置がthresholdだ。値を上げると被写体を細らせ、下げると太らせる。

次の softness は境界の柔らかさを受け持つ。ここにhalf_widthという一手間がある。softness / 100.0 * 127.0 で半値幅を出し、これが 1.0 未満のときは np.where で完全な2値化に切り替える。除算式 (m - (threshold - half_width)) / (2.0 * half_width) をそのまま使うと、softnessが0に近いとき分母が極小になって、境界のたった1画素が中間の灰色として残ってしまう。ロゴやアイコンのように輪郭をパキッと出したい素材で、この1画素の滲みが目立つ。half_width < 1.0 の分岐は、その滲みを断ち切って純粋な白黒を保証するための場合分けだ。

    # (2) エッジ収縮↔膨張
    if edge_shift != 0:
        k = abs(int(edge_shift))
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2 * k + 1, 2 * k + 1))
        if edge_shift < 0:
            m = cv2.erode(m, kernel)
        else:
            m = cv2.dilate(m, kernel)

    # (3) ノイズ除去
    if noise > 0:
        kernel = np.ones((3, 3), np.uint8)
        m = cv2.morphologyEx(m, cv2.MORPH_OPEN, kernel, iterations=int(noise))

    # (4) 境界ぼかし
    if blur > 0:
        b = int(blur)
        if b % 2 == 0:
            b += 1
        m = cv2.GaussianBlur(m, (b, b), 0)
    return m

3本目の edge_shift はエッジの収縮と膨張だ。値が負なら cv2.erode でマスクを内側に食い込ませ、正なら cv2.dilate で外へ広げる。楕円カーネルの一辺を 2 * k + 1 で作るのは、モルフォロジー処理のカーネルを必ず奇数サイズにして中心画素を持たせるためだ。AIが背景をひと筋残したときはマイナス側へ、被写体の縁を削りすぎたときはプラス側へ、1〜2px動かすだけで縁のズレが揃う。

4本目の noisecv2.MORPH_OPEN(収縮のあと膨張)の反復回数を渡す。オープニングは小さな白い孤立点を消す処理で、背景に飛び散った数画素のゴミを、被写体本体を痩せさせずに掃除する。回数をスライダーで直に持たせているので、ゴミが多い素材では2〜3回、繊細な縁を残したい素材では0回、と現物を見ながら決められる。

最後の blurcv2.GaussianBlur による境界ぼかしだ。ここに if b % 2 == 0: b += 1 がある。GaussianBlurのカーネルサイズは奇数でなければOpenCVが例外を投げる。スライダーは0〜25の連続値なので偶数も来る。偶数が来たら+1して奇数へ丸める、この一行が無いとblurを偶数値にした瞬間にアプリが落ちる。合成時にジャギーを消してエッジを馴染ませる仕上げの一手だ。

5本を通した結果は、あくまで「整えた後処理マスク」でしかない。ここにはまだブラシの手直しも元画像のアルファも入っていない。それらを重ねるのが次のレイヤーだ。

Step 2. ブラシは結果に直接描かず、別レイヤーへ塗る

後処理でも取りきれない箇所は、最後は人が手で塗る。消去ブラシで消し残しを削り、復元ブラシで消えすぎた部分を戻す。ここで肝になる設計判断が、ブラシは最終画像に直接描かないという点だ。塗った内容は erase_layerrestore_layer という2枚の専用レイヤーに溜める。後処理マスクとは別の場所に持つ。

復元ブラシのカーソル円が出た修正中の画面
復元ブラシを選ぶと結果ビューに青い円カーソルが出る。ここを塗ると消えすぎた部分を戻せる。塗り跡は結果画像に焼かず専用の復元レイヤーへ蓄積するので、後からスライダーを動かしても保持される。

塗りの本体は mask_pipeline.pypaint_brush_stroke だ。ブラシ1点をレイヤーに描き込む純関数で、円の中心から外周に向かう硬さの減衰(hardness falloff)を計算し、既存のレイヤーとmax合成する。

# mask_pipeline.py
def paint_brush_stroke(layer, center_xy, size, hardness):
    h, w = layer.shape[:2]
    radius = max(int(size) // 2, 1)
    x, y = int(center_xy[0]), int(center_xy[1])

    x0, x1 = max(x - radius, 0), min(x + radius + 1, w)
    y0, y1 = max(y - radius, 0), min(y + radius + 1, h)
    if x0 >= x1 or y0 >= y1:
        return

    yy, xx = np.mgrid[y0:y1, x0:x1]
    dist = np.sqrt((yy - y) ** 2 + (xx - x) ** 2) / radius  # 0=中心, 1=外周

    hard = hardness / 100.0
    # hard 部分(中心〜hard*radius)は255、外側は線形減衰
    falloff = np.clip((1.0 - dist) / max(1.0 - hard, 1e-3), 0, 1)
    stamp = (np.clip(falloff, 0, 1) * 255).astype(np.uint8)
    stamp[dist > 1.0] = 0

    region = layer[y0:y1, x0:x1]
    np.maximum(region, stamp, out=region)

距離マップ dist は中心で0、外周で1になるよう半径で正規化してある。硬さ hard は0〜1で、falloffは (1.0 - dist) / max(1.0 - hard, 1e-3)。hardが1に近ければ分母が極小になり、円のほぼ全域が255になってハードエッジのスタンプになる。hardが0なら中心から外周までなだらかに減衰する柔らかいスタンプだ。分母を max(..., 1e-3) で下限を切っているのはゼロ除算よけで、hardが100でもクラッシュしない。円の外側(dist > 1.0)は0に落として四角い塗り残しを防ぐ。

そして最後の np.maximum(region, stamp, out=region) がmax合成だ。同じ場所を何度もなぞると、より濃い方(大きい値)が残る。ドラッグで筆を往復させても塗り跡が薄まらず、期待どおり「塗るほど濃くなる」感触になる。out=region でスライスへ直接書き戻すので、レイヤーがその場で更新される。

この2枚のレイヤーに溜める設計の御利益が、スライダーとの独立性だ。復元ブラシで髪の毛先を塗り戻したあとで、しきい値スライダーを動かして全体の切り位置を変えたとする。塗った内容は restore_layer に別で残っているので、後処理をやり直しても毛先の修正は消えない。合成のたびに後処理マスクとブラシレイヤーを重ね直すからだ。「AIをかけ直す」「スライダーを動かす」「ブラシで直す」の3つが、どの順番でも壊れ合わない。UI側の _paint_at は、いま選んでいるツールに応じて塗り先のレイヤーを選ぶだけでいい。

# bg_remover_ui_ux.py
def _active_brush_layer(self):
    """現在のブラシツールに対応するレイヤーを返す(なし=None)。"""
    tool = self.brush_tool.currentText()
    if tool == "消去ブラシ":
        return self.erase_layer
    if tool == "復元ブラシ":
        return self.restore_layer
    return None

Step 3. 合成の優先順位:消去 > 復元 > ベース

後処理マスク・消去レイヤー・復元レイヤー・元画像の既存アルファ、この4枚を1枚の最終アルファにまとめるのが compose_final_alpha だ。ここには明確な優先順位がある。復元でベースを持ち上げ、消去でいちばん最後に削る。塗った手直しを確実に反映させる順序だ。

# mask_pipeline.py
def compose_final_alpha(processed, erase_layer, restore_layer, original_alpha):
    f = processed.astype(np.int32)  # int16 だと erase*f (最大65025) が溢れる
    f = np.maximum(f, restore_layer.astype(np.int32))
    f = f - erase_layer.astype(np.int32) * f // 255  # 消去は割合で減算
    f = np.clip(f, 0, 255).astype(np.uint8)

    if original_alpha is not None:
        f = cv2.bitwise_and(f, original_alpha)
    return f

処理は3段だ。np.maximum(f, restore_layer) で復元ブラシの値を後処理マスクに重ねる。消えていた被写体が復元レイヤーの濃さまで戻る。続く f - erase_layer * f // 255 が消去で、割合で減算するのがポイントだ。消去レイヤーが255の画素は完全に透明になり、128なら現在値の半分だけ削れる。硬さの弱いブラシで縁をなぞると自然に薄れる。消去を復元より後に置くことで、「消したいものは必ず消える」を保証している。

コメントの int32 にする理由 は見逃せない。erase_layer * f は、両方が最大255なら 255 * 255 = 65025 になる。int16の上限は32767なので、この積はオーバーフローして符号が壊れる。もし気づかずint16のまま計算すると、消去ブラシを強く効かせた瞬間にアルファ値が化けて、透明にしたい場所が逆に真っ白になるような不可解なバグが出る。だから積を作る前に astype(np.int32) で器を広げてある。コメントの一文は、その落とし穴を後で読む人に残した実装メモだ。

最後の cv2.bitwise_and(f, original_alpha) は、元画像がすでに透明部分を持っていた場合の処理だ。PNGなどで既存アルファがある素材では、元から透明だった領域を計算結果とANDして必ず透明に保つ。既存の透明を後処理が塗り潰してしまわないための歯止めになる。

💡 再利用できる設計知見:手直しを効かせる合成は、①足す操作(復元)を先に、削る操作(消去)を後に置く ②削りは0/1でなく割合で引く ③積を作る前に器の型を広げてオーバーフローを断つ。この3点があれば、修正レイヤーを何枚重ねても「消したいものは消える/型化けしない」が守られる。ペイント系の合成を書くときにそのまま持ち込める型だ。

Step 4. 20段のUndo:空振りクリックでスタックを汚さない

ブラシで塗る作業には取り消しが要る。復元も消去も、この undo_stack という1本のスタックで一括して戻せる。1手を戻すたびに2枚のブラシレイヤーが直前の状態へ復帰する。仕組みは素朴で、塗る直前に現在の2レイヤーのコピーをタプルで積む。

# bg_remover_ui_ux.py
def _push_undo(self):
    self.undo_stack.append(
        (self.erase_layer.copy(), self.restore_layer.copy()))
    if len(self.undo_stack) > 20:
        self.undo_stack.pop(0)

(erase_layer.copy(), restore_layer.copy()) のタプルを積むので、1手戻すと消去と復元がセットで巻き戻る。上限は20段で、超えたら pop(0) で最古の1件を捨てる。フルサイズの画像レイヤー2枚を無制限に溜めるとメモリを食い続けるので、直近20手だけを保持する割り切りだ。実際のブラシ作業で20手より前に戻したい場面はほとんど来ない。

細かいが効いているのが、いつUndoを積むかの判定だ。マウスを押した瞬間には積まない。実際にキャンバスへ描き込む直前まで待って積む。制御しているのが _stroke_undo_pushed フラグだ。

# bg_remover_ui_ux.py
def _paint_at(self, x, y):
    layer = self._active_brush_layer()
    if layer is None or self.original_bgr is None:
        return False
    h, w = layer.shape[:2]
    if not (0 <= x < w and 0 <= y < h):
        return False
    if not self._stroke_undo_pushed:
        # 空振りクリックでスタックを汚さないよう、最初に実際に描く直前に積む
        self._push_undo()
        self._stroke_undo_pushed = True
    paint_brush_stroke(layer, (x, y),
                       size=self.brush_size.value(),
                       hardness=self.brush_hardness.value())
    return True

ストロークの開始時に _stroke_undo_pushed をFalseへ戻し、実際に描く1回目だけUndoを積んでTrueにする。ドラッグ中は何十回も _paint_at が呼ばれるが、Undoが積まれるのはストロークにつき1回だけだ。1ドラッグ=1手として戻せる。もし画像の外をクリックしたり、ツールが「なし」のまま押しただけなら、_paint_at は先頭のガードで抜けてUndoを積まない。この空振り対策が無いと、キャンバスの端を無駄クリックするたびにUndo履歴が同じ状態のコピーで埋まり、20段がすぐに使い果たされる。戻す処理は積んだタプルを取り出して差し替えるだけだ。

# bg_remover_ui_ux.py
def undo_brush(self):
    if not self.undo_stack:
        return
    self.erase_layer, self.restore_layer = self.undo_stack.pop()
    self.update_preview()

スタックが空なら黙って返し、あれば末尾のタプルを2レイヤーへ展開して update_preview で再描画する。ブラシ側だけを巻き戻すので、スライダーやAIの状態はそのまま残る。手で塗った1手だけを、他を巻き込まずに取り消せる。

Step 5. 表示切替3種と、チェッカー背景のキャッシュ

仕上げの確認には、完成画像だけでなくマスクそのものを見たい場面がある。update_preview は表示コンボの選択に応じて、完成画像・マスク表示・背景検出の3種を描き分ける。どのモードでも最終アルファは同じ compose_final_alpha から取り、見せ方だけを変える。

マスク表示ビュー(白黒マスク)
表示切替「マスク表示」。右ビューに白黒のアルファマスクが出る。白=被写体、黒=背景。境界のグレーの帯を見れば、しきい値やぼかしの効き具合を目で確かめられる。
# bg_remover_ui_ux.py
def update_preview(self):
    if self.original_bgr is None or self.base_mask is None:
        return
    alpha = self.compute_final_alpha()

    rgba = cv2.cvtColor(self.original_bgr, cv2.COLOR_BGR2BGRA)
    rgba[:, :, 3] = alpha
    self.preview_rgba = rgba

    display_mode = self.display_combo.currentText()
    if display_mode == "マスク表示":
        display = cv2.cvtColor(alpha, cv2.COLOR_GRAY2RGB)
    elif display_mode == "背景検出":
        display = cv2.cvtColor(255 - alpha, cv2.COLOR_GRAY2RGB)
    else:
        checker = self.create_checkerboard(rgba.shape[1], rgba.shape[0])
        rgb = cv2.cvtColor(self.original_bgr, cv2.COLOR_BGR2RGB)
        a = alpha.astype(np.float32)[:, :, np.newaxis] / 255.0
        display = (rgb * a + checker * (1 - a)).astype(np.uint8)

    self.preview_view.set_image(np_to_qimage_rgb(display))

「マスク表示」はアルファをそのままグレースケールとして出す。白が被写体、黒が背景で、境界のグレーの帯を見ればしきい値やぼかしの効き方が一目で分かる。「背景検出」は 255 - alpha で明暗を反転させ、どこが背景と判定されたかを白く見せる。消し残しを探すときに向く。「完成画像」は透明部分にチェッカー柄を敷き、アルファ a で被写体とチェッカーをアルファブレンドする。rgb * a + checker * (1 - a) が透過合成の式で、半透明の縁が背景に自然に溶ける様子まで確認できる。保存用の preview_rgba はどのモードでも同じ最終アルファで作るので、画面の見せ方に関係なく書き出す絵は一定だ。

チェッカー背景には create_checkerboard でキャッシュを効かせてある。透過を確認する市松模様は、画像サイズが同じなら毎回まったく同じものだ。スライダーをドラッグすると update_preview が毎フレーム走るので、そのたびに市松を生成し直すと大きな画像で目に見えて重くなる。

# bg_remover_ui_ux.py
def create_checkerboard(self, w, h):
    # 毎フレーム再生成すると大画像でスライダーが重くなるためサイズ別にキャッシュ
    if (self._checker_cache is not None and
            self._checker_cache.shape[:2] == (h, w)):
        return self._checker_cache
    size = 20
    img = np.zeros((h, w, 3), dtype=np.uint8)
    c1, c2 = 60, 90
    yy, xx = np.mgrid[0:h, 0:w]
    cells = ((xx // size) + (yy // size)) % 2
    img[cells == 0] = c1
    img[cells == 1] = c2
    self._checker_cache = img
    return img

キャッシュ済みの市松があり、しかも現在の (h, w) と形が一致するときだけ、それをそのまま返す。画像を読み替えてサイズが変われば形の比較が外れ、新しい市松を1度だけ作り直してキャッシュを更新する。20px角のマスを (xx // size + yy // size) % 2 で市松にし、明度60と90の2色を敷く。地味な最適化だが、スライダーを動かしたときのプレビュー追従がなめらかになる差は大きい。

設計Q&A:ブラシとレイヤーの疑問

Q. ブラシで塗った結果を、最終画像に直接焼き込んでしまえば楽では?
A. 楽になるのは一瞬だけで、後が破綻する。最終画像に直接描くと、あとからしきい値スライダーを動かした瞬間に画像が再合成されて、塗った跡が消し飛ぶ。erase_layerrestore_layer に分けて溜めるのは、後処理とブラシ修正を何度でも重ね直せるようにするためだ。塗り→スライダー→塗り→AIかけ直し、をどの順で行き来しても手直しが生き残るのは、この分離があるからだ。

Q. Undoが20段で足りるのか。無制限にしないのはなぜ?
A. 1手ぶんがフルサイズのアルファレイヤー2枚のコピーで、無制限に積むとメモリを際限なく食う。実際のブラシ作業で20手より前に戻したい場面はまず来ないので、上限20段で pop(0) する割り切りにした。数値そのものより、空振りクリックで履歴を汚さない _stroke_undo_pushed の仕掛けの方が体感に効く。20段を無駄なコピーで浪費しないので、実効的な取り消し回数が保たれる。

まとめ:第5回の要点

  • 5スライダー後処理postprocess_mask がthreshold中心のレベル補正・half_width<1.0での完全2値化・erode/dilate・MORPH_OPEN・GaussianBlurの奇数化を1関数で担う。純関数なのでAIにも古典CVにも同じく通る。
  • ブラシは別レイヤーpaint_brush_stroke がhardness falloffとmax合成で塗り、消去/復元の2レイヤーに溜める。だからスライダーを後から動かしても修正が保持される。
  • 合成の優先順位compose_final_alpha は復元で持ち上げ消去で最後に削る。積のオーバーフローを避けるため int32 に広げる。既存アルファはANDで守る。
  • 20段Undo_push_undo のタプルスタックと _stroke_undo_pushed で、1ドラッグ=1手・空振りクリックは履歴を汚さない。
  • 表示切替3種update_preview が完成画像・マスク表示・背景検出を描き分け、create_checkerboard のサイズ別キャッシュでプレビュー追従を軽く保つ。

これでAIが抜いた9割の上に、後処理とブラシで残り1割を乗せる仕上げの一本道が通った。次回(第6回)はUI/UXを扱う。QGraphicsViewのズームで毛先を拡大し、スポイトとマジックワンドのクリックを連携させ、十数秒かかるAI推論と数十枚の一括処理をQThreadへ逃がして画面を固まらせない設計、そしてドラッグ&ドロップでの一括保存までを、今回作った仕上げレイヤーの上に組み上げる。

この連載について:Background Removal Studio Pro は、設計・実装の各工程でAIを併用して開発した個人プロジェクトです。掲載するコードは実際のソースからの抜粋で、動作は自動テスト(pytest)と実機で検証しています。© 2026 Cooliris(記事本文と掲載コードの権利は作者に帰属します)。


👉 ▶ この連載のハブ(全7回の地図)バイブコーディング開発実例いろんなアプリの作り方

Claude Codeのトークンを削るOSS 11本 — ライセンス本文まで確かめた一覧前のページ

2026年8月に並ぶ5つの廃止期限 — grep 2本で自分のリポジトリを監査する次のページ

ピックアップ記事

  1. 高精度OCRデスクトップアプリの作り方 — PaddleOCR-VLとPyIns…

  2. Claude Mission Control の作り方 — Tauri+Pyth…

  3. New Eden Intelligence Hub の作り方 — EVE Onl…

  4. 競艇予想AIの作り方 — LightGBMで「当たる順位」を学習させる実装ガイド…

関連記事

  1. 都市開発シミュを作る④|4度つまずいて座標系ごと作り直した話 — 真のアイソメグリッド移行【Aurum City制作】
  2. はじめての“動くアプリ”を1本作る|メモ帳をステップバイステップで【入門4】

    バイブコーディング

    はじめての“動くアプリ”を1本作る|メモ帳をステップバイステップで【入門4】

    コードを1行も書かず、AIに頼んで出てきたHTMLを保存・ダブルクリッ…

  3. large-v3-turbo は large-v3 の代わりになるか。日本語で測って、速度の測り方を2回間違えた記録
  4. Grokで回すXメディア生成パイプラインの作り方 — 検索から画像・音声・動画まで自動化する
  5. 競艇予想AIの作り方 — LightGBMで「当たる順位」を学習させる実装ガイド

    アプリの作り方

    競艇予想AIの作り方 — LightGBMで「当たる順位」を学習させる実装ガイド

    過去21万レースを学習し3連単上位10点を出す競艇予想AIの作り方。な…

  6. WorkSpace Explorer の作り方 — 増えた自作アプリを一画面で束ねる Electron 製の開発司令塔

    アプリの作り方

    WorkSpace Explorer の作り方 — 増えた自作アプリを一画面で束ねる Electro…

    作業フォルダのプロジェクトが増えて「どれが何で最後にいつ触ったか」を見…

注目

AIで、ここまで作れる

AIで作った2D RPGを、ブラウザでそのまま遊べます。その「作り方=最後まで完成させる進め方」も実例つきで公開中。

▶ ゲームを遊ぶやり方を読む

PR

お名前.com 独自ドメイン取得(PR)

独自ドメイン:お名前.com(本サイトで使用・PR)

  1. Anthropic「Claude Science」に学ぶ — 個人開発者が作れるドメイン特化AIワークベンチの型

    AI・テック動向

    Anthropic「Claude Science」に学ぶ — 個人開発者が作れる…
  2. Gemini 3.6 Flash は出力トークンが約17%減る — 単価ではなく「実出力トークン×単価」で比べる

    AI・テック動向

    Gemini 3.6 Flash は出力トークンが約17%減る — 単価ではなく…
  3. Claude Sonnet 5 が Claude Code の既定モデルに — 1Mコンテキストと月コスト激減を実額で検証

    AI・テック動向

    Claude Sonnet 5 が Claude Code の既定モデルに — …
  4. JavaScriptでRPGを作る②|データ駆動設計 — 敵・職業・スキルを“データ追記だけ”で増やす【Archipelago Saga制作】

    アプリの作り方

    JavaScriptでRPGを作る②|データ駆動設計 — 敵・職業・スキルを“デ…
  5. Claude API が会話途中の system メッセージに対応 — キャッシュを壊さず方針を差し替える

    AI・テック動向

    Claude API が会話途中の system メッセージに対応 — キャッシ…
PAGE TOP

TAG CLOUD

ドラッグで回転・クリックでそのタグの記事一覧へ