画像・音声処理

【1分でわかる】OpenCVの二値化がわかる!その種類と操作方法を解説

OpenCVで二値化は比較的簡単に実施可能ですが、いざ二値化をしてみると

うまく分離できなくて、画像の特徴が表せない!

画像の違いがはっきりしないな・・・

という悩みを持った方はいませんか?今回はOpenCVの二値化について、簡単に二値化をするところから一歩踏み込んだ内容を確認していきたいと思います。


本ブログを運営しているTech Teacherは、
プログラミング家庭教師サービスを運営しています。
完全マンツーマン・フルオーダーメイド
あなたが必要な指導を提供します。

OpenCVとは

OpenCVはオープンソースのコンピュータビジョン用ライブラリです。主に

  • 画像・動画の読み込み
  • 画像処理
  • 画像認識

などを実施ずることが可能です。

OpenCV全般に関しては、以下の記事でも取り扱っていますので、参考にしてください。

【1分でわかる】初心者でも簡単にOpenCVで画像認識の実装ができるやり方を学ぶ!OpenCVで画像認識をしてみようとお考えの方に向けて、OpenCVを使ってそもそも何ができて、何のためにそのようなことをするのかを解説します。そして初心者でも簡単にPythonで画像認識を実行する手法を見ていきます。実際にコードを示しながら進めているので、一緒に手を動かしながら学べます!...

OpenCVのインストールから全般的な使い方に関しては、以下の記事でも取り扱っていますので、参考にしてください。

Python + OpenCVで画像処理をマスター!使用法・実用例を解説Python初心者の方でOpenCVの使い方について悩んでいる人必見。OpenCVの基礎知識やインストール方法、使い方を網羅しました。OpenCVを使用した画像動画処理について悩んでいる人は参考にしてください。...

OpenCVの二値化

「二値化」とは、その名の通り画像を「白」と「黒」の2色に変換する処理のことです。その際に閾値を決め、その閾値に従って二値化を行います。

二値化を行うことで、画像を鮮明にしたり単純にしたりすることができるので分析の際に多く使われます。

しかし単純に二値化をするだけでは、画像を鮮明にしたくて二値化したものの、下の画像のように全体的にもやっとした画像になってしまうこともあります。

今回はいろいろな操作をすることによりきれいに二値化できないか試してみたいと思います。

openCV二値化の操作

まずは二値化の操作をおさらいしておきましょう。

img = cv2.imread('./Sample.jpg' ,0)
thr, img_th = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY)
cv2.imshow('Image', img_th)
cv2.waitKey()
img = cv2.imread('./Sample.jpg' ,0)

まずは「cv2.imread()」で対象となる画像を読み込んでいます。カッコの中は一つ目が読み込む画像、二つ目の「0」はグレースケールで読み込むことを指定しています。

thr, img_th = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY)

thr, img_th = cv2.threshold()」の部分で二値化を行っています。2変数が取り出され、1つ目、今回の場合は「thr」には閾値が入ります。2つ目、今回の場合は「img_th」に二値化されたデータが入ります。

引数は、前から順番に「入力する画像」「閾値(下限)」「閾値(上限)」「閾値指定方法」です。

4つ目の閾値指定方法を以下にまとめておきます。

  • cv2.THRESH_BINARY:閾値(下限)以下の値を0、それ以外の値を閾値(上限)にして2値化を行います。
  • cv2.THRESH_BINARY_INV:閾値(下限)以下の値を閾値(上限)、それ以外の値を0にして2値化を行います。
  • cv2.THRESH_TRUNC:閾値(下限)以下の値はそのままで、それ以外の値を閾値(上限)にします。
  • cv2.THRESH_TOZERO:閾値(下限)以下の値を0、それ以外の値はそのままにします。
  • cv2.THRESH_TOZERO_INV:閾値(下限)以下の値はそのままで、それ以外の値を0にします。
  • cv2.THRESH_OTSU:大津の手法で閾値を自動的に決める場合に指定します。
  • cv2.THRESH_TRIANGLE:ライアングルアルゴリズムで閾値を自動的に決める場合に指定します。

    OpenCV二値化の閾値の調整について

    閾値を自動で設定する

    さきほど手動で設定した場合になんとなくうまく分けることができなかったので、自動で閾値を設定してみましょう。

    img = cv2.imread('./Sample.jpg' ,0)
    thr, img_th = cv2.threshold(img, 100, 255, cv2.THRESH_OTSU)
    cv2.imshow('Image', img_th)
    cv2.waitKey()

    2行目の閾値分離方法を「cv2.THRESH_OTSU大津の二値化に変更してみました。この時に使用した閾値は、2行目で「thr」に格納しているので、これを確認すると数値がわかります。

    今回使用した大津の二値化ですが、画像内に存在する画素をヒストグラムに取り、左側の黒に属するクラスと、右側の白に属するクラスに分け、一番分離ができる部分で閾値を自動で決める方法です

    よい閾値を探してみる

    list1 = [25, 50, 75, 100, 125, 150, 175, 200]
    img = cv2.imread('./Sample.jpg' ,0)
    plt.figure(figsize=(20, 10))
    for i, j in enumerate(list1):
        plt.subplot(2, 4, i+1)
        thr, img_th = cv2.threshold(img, j, 255, cv2.THRESH_BINARY)
        img_th = cv2.cvtColor(img_th, cv2.COLOR_RGB2BGR)
        plt.title(f'threshold:{j}')
        plt.imshow(img_th)

    実際に閾値によって画像がどのように変化するかはやってみるのが一番なので、グリッドサーチ的に閾値を変化させ二値化をしてみました。実際には大津の方法であたりをつけた後、さらにこの方法で確認すると好みの値に仕上がると思います

    list1 = [25, 50, 75, 100, 125, 150, 175, 200]
    img = cv2.imread('./Sample.jpg' ,0)

    実際に試してみる閾値をリストで渡してやります。その後、二値化するデータを読み込みます。

    plt.figure(figsize=(20, 10))

    画像を書く準備をします。今回は一覧で表示したいので、matplotlibで描画する前提にしています。

    for i, j in enumerate(list1):

    for文でリストの内容分だけ二値化をします。enumerateはlistの内容と別に、試行回数を0から順番に出力します。今回の場合だと

    • i=0, j=25
    • i=1, j=50
    • i=2, j=75
    • ・・・
    • i=7, j=200

    の順でi, jに数値が入った状態でfor文が回ります。

    plt.subplot(2, 4, i+1)

    for文ごとに画像を表示する位置を指定します。今回は「i+1」番目のところに画像を表示します。

    thr, img_th = cv2.threshold(img, j, 255, cv2.THRESH_BINARY)

    リストの値、for文でjの部分に代入した値で二値化の処理を行います。

    img_th = cv2.cvtColor(img_th, cv2.COLOR_RGB2BGR)

    cv2はRGBで処理をしているのに対し、matplotlibはBGRで処理をしているので変換を行います。変換を行わないとこのような色で表示されます。

        plt.title(f'threshold:{j}')
        plt.imshow(img_th)

    最後にタイトルを設定して、画像を描画します。

    データサイエンスを学習するならTech Teacherで!

    『Tech Teacher』3つの魅力

    魅力1. オーダーメイドのカリキュラ

    『Tech Teacher』では、決められたカリキュラムがなくオーダーメイドでカリキュラムを組んでいます。「質問だけしたい」「相談相手が欲しい」等のご要望も実現できます。

      魅力2. 担当教師によるマンツーマン指導

      Tech Teacherでは完全マンツーマン指導で目標達成までサポートします。
      東京大学を始めとする難関大学の理系学生・院生・博士の教師がが1対1で、丁寧に指導しています。
      そのため、理解できない箇所は何度も分かるまで説明を受けることができます。

      魅力3. 3,960円/30分で必要な分だけ受講

      Tech Teacherでは、授業を受けた分だけ後払いの「従量課金制」を採用しているので、必要な分だけ授業を受講することができます。また、初期費用は入会金22,000円のみです一般的なプログラミングスクールとは異なり、多額な初期費用がかからないため、気軽に学習を始めることができます。

      まとめ

      ・魅力1. 担当教師によるマンツーマン指導

      ・魅力2. オーダーメイドのカリキュラム

      ・魅力3. 3,960円/30分で必要な分だけ受講

      質問のみのお問い合わせも受け付けております。

      まとめ

      今回はいくつかの方法で二値化を試してみました。二値化はいろいろな局面で非常に有効な手段になりえますが、うまく二値化できずに画像がまっくろになったり、白飛びしたような画像になってしまったことも多々あると思います。

      今回の内容を確認いただき、うまく二値化を使いこなしていただければと思います。