Cv2.BitwiseAnd の使い方【OpenCV/C#(OpenCvSharp)】〜ビット演算とマスク処理〜

OpenCV for C#
📌 準備: OpenCV の環境構築がまだの方はこちら → C++ 環境構築ガイド / C#(OpenCvSharp)セットアップ

Cv2.BitwiseAnd は2枚の画像(または画像とマスク)に対してビット単位のAND演算を行う関数です。マスクを使った領域切り抜きや、色抽出後の画像合成で頻繁に使います。最小コードは次のとおりです。

Cv2.BitwiseAnd(src1, src2, dst, mask);

動作環境

  • OpenCV 4.x(OpenCvSharp4)
  • .NET 8 コンソールアプリ
  • NuGet: OpenCvSharp4 + OpenCvSharp4.runtime.win(Windows実行時)

環境構築がまだの方は環境構築ガイドを先にどうぞ。


基本の使い方

まず BitwiseAnd の最もシンプルな例として、2枚の画像に対してAND演算を行います。

using OpenCvSharp;

// 2枚の単色画像を AND 演算する
using var img1 = new Mat(300, 300, MatType.CV_8UC3, new Scalar(0, 255, 255));  // 黄色
using var img2 = new Mat(300, 300, MatType.CV_8UC3, new Scalar(255, 255, 0));  // シアン
using var dst = new Mat();

// ビット AND:チャンネルごとにビット演算
Cv2.BitwiseAnd(img1, img2, dst);

Cv2.ImShow("BitwiseAnd", dst);
Cv2.WaitKey(0);
Cv2.DestroyAllWindows();

黄色(B=0, G=255, R=255)とシアン(B=255, G=255, R=0)の AND は、各チャンネルをビット単位で AND した結果(B=0, G=255, R=0)= 緑色になります。


引数と戻り値

Cv2.BitwiseAnd

引数 型 説明
src1 Mat 入力画像1
src2 Mat 入力画像2(src1 と同サイズ・同チャンネル)
dst Mat 出力画像(in-place 可)
mask Mat? 処理対象ピクセルを指定するマスク(省略可・8ビットシングルチャンネル)

戻り値は void。dst に結果が書き込まれます。

他のビット演算関数

関数 演算 主な用途
Cv2.BitwiseAnd AND マスク適用・共通部分の抽出
Cv2.BitwiseOr OR 2枚の画像の合成
Cv2.BitwiseXor XOR 差分検出・透かし
Cv2.BitwiseNot NOT マスクの反転

実践例

実践例1: マスクを使った色領域の切り抜き

Cv2.InRange でHSV画像から特定色のマスクを生成し、BitwiseAnd で元画像から色領域だけを切り抜く定番パターンです。Cv2.InRange の使い方も合わせて参照してください。

using OpenCvSharp;

// 画像ファイルを読み込む(BGR)
using var src = Cv2.ImRead("input.jpg", ImreadModes.Color);
if (src.Empty()) throw new Exception("画像を読み込めませんでした");

// HSV に変換
using var hsv = new Mat();
Cv2.CvtColor(src, hsv, ColorConversionCodes.BGR2HSV);

// 赤色のHSV範囲でマスクを作成(赤は Hue が 0〜10 と 170〜180 に分かれる)
using var mask1 = new Mat();
using var mask2 = new Mat();
using var mask  = new Mat();
Cv2.InRange(hsv, new Scalar(0, 100, 100), new Scalar(10, 255, 255), mask1);
Cv2.InRange(hsv, new Scalar(170, 100, 100), new Scalar(180, 255, 255), mask2);
Cv2.BitwiseOr(mask1, mask2, mask);  // 2つの範囲を合算

// マスクを使って元画像から赤色領域だけを切り抜く
using var result = new Mat();
Cv2.BitwiseAnd(src, src, result, mask);

Cv2.ImShow("mask", mask);
Cv2.ImShow("result", result);
Cv2.WaitKey(0);
Cv2.DestroyAllWindows();

BitwiseAnd(src, src, result, mask) という形式がポイントです。src1 と src2 を同じにすることで、マスクが 1 のピクセルだけを src からそのままコピーする効果になります。


実践例2: 円形マスクで画像を丸く切り抜く

描画関数で作ったマスクを組み合わせる例です。

using OpenCvSharp;

using var src = Cv2.ImRead("input.jpg", ImreadModes.Color);
if (src.Empty()) throw new Exception("画像を読み込めませんでした");

// 黒マスクを用意し、中央に白い円を描画
using var mask = new Mat(src.Size(), MatType.CV_8UC1, Scalar.Black);
var center = new Point(src.Width / 2, src.Height / 2);
int radius = Math.Min(src.Width, src.Height) / 2;
Cv2.Circle(mask, center, radius, Scalar.White, thickness: -1); // 塗りつぶし

// マスクで円形に切り抜く
using var result = new Mat();
Cv2.BitwiseAnd(src, src, result, mask);

Cv2.ImShow("circle crop", result);
Cv2.WaitKey(0);
Cv2.DestroyAllWindows();

Cv2.Circle の thickness: -1 で塗りつぶし円を描き、それをマスクとして使います。Cv2.ConnectedComponentsWithStats などと組み合わせることで、ラベリング結果の特定領域をそのまま切り抜くことも可能です。


つまずきポイント

⚠️ mask は必ず 8ビットシングルチャンネル(CV_8UC1)

BitwiseAnd の mask 引数にはシングルチャンネルの Mat のみ有効です。BGR 画像(3チャンネル)をそのままマスクに渡すと意図しない結果になるか、例外が発生します。Cv2.CvtColor や Cv2.InRange の出力(CV_8UC1)をそのまま使うのが確実です。

⚠️ src1 と src2 のサイズ・チャンネルが一致しないと例外

両入力のサイズ・チャンネル数・深度が完全に一致している必要があります。リサイズ後の画像と元画像を混在させるケースで発生しやすいミスです。事前に src.Size() や src.Type() で確認してください。

⚠️ Mat の Dispose 漏れに注意

中間生成する Mat(mask1、mask2、result 等)はすべてネイティブメモリを持ちます。using を必ず付けてください。ループ内で生成している場合は特に漏れやすく、長時間稼働するアプリでメモリが増加し続ける原因になります。


関連する関数


まとめ

Cv2.BitwiseAnd はマスクを指定できる第4引数が実務での主役です。Cv2.InRange や描画関数でマスクを作り、BitwiseAnd(src, src, dst, mask) の形で使うパターンを覚えておくと、色抽出・領域切り抜きの大半に対応できます。mask は必ず CV_8UC1 で渡し、中間 Mat はすべて using で解放してください。

🛠 画像処理のプロが開発するSDK/API

本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/APIを開発しています。SDK は C#/.NET 8 に正式対応しており、OpenCvSharp を使うプロジェクトからそのまま組み込めます。

→ 顔認証のなりすまし対策 設計チェックリスト(当ブログ)
→ なりすまし判定SDK/APIの詳細を見る
→ API仕様書・サンプルコード

タイトルとURLをコピーしました