質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.54%

  • Python 3.x

    6297questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • OpenCV

    1063questions

    OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

エッジの2値画像から4連結した画素のみをプロットしたい

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 167

Do_you_1isten

score 15

 前提・実現したいこと 

複数枚の写真からガラスなどの反射による映り込みを除去した背景写真を生成する論文からプログラムを実装しようとしています.

この論文内でエッジ画像から4連結した画像のみをプロットする処理を実装したいです.

順を追って説明します.
上記論文ではまず,入力画像からエッジを取得します.このエッジ画像はエッジ部を白,それ以外を黒とする画像です.以下に実際のエッジ画像の例を図1に示します.

図1 エッジ画像例
_            図1 エッジ画像例

このエッジ画像を使って,各画素を探索します.このとき,探索対象画素の周囲の9画素の内,エッジの画素である画素が4画素以上ならば,その探索画素をプロットする処理を実装したいです.

私自身で実装したコードを該当のソースコードに示します.

些細なことでも良いのでアドバイス頂けますと助かります.

 発生している問題

該当のソースコードから得られた出力画像を図2に示します.

該当のソースコードの実行例
_        図2 該当のソースコードから得られた出力画像

該当のソースコードから得られた出力画像の問題点として,そもそも,エッジのない画素にエッジをプロットしているという問題が起こっています.以下に具体的な例の図3,図4,図5,図6に示します.

入力注目画像
_         図3 エッジ画像での赤枠の範囲が図4

入力拡大画像
_         図4 エッジ画像での図3の赤枠の拡大画像

出力注目画像
_         図5 出力画像での赤枠の範囲が図6

出力拡大画像
_         図6 出力画像での図5の赤枠の拡大画像

図4,図6を比較すると,図4のエッジ画像で存在していたエッジが図6では消えていることがわかります.

 該当のソースコード

import cv2
import numpy as np

def count_neibor(binary_image):
    image_thinned = binary_image.copy()
    #画像の縦と横のサイズを取得
    rows, columns = image_thinned.shape
    #プロットする画像を宣言
    dist_image = np.zeros(image_thinned.shape,dtype=np.uint8)

    #各画素を探索
    for x in range(1, rows - 1):
        for y in range(1, columns -1):

            #探索画素から近傍画素を設定
            neighbour_points = neighbours(x, y, image_thinned)
            #近傍画素にエッジが4以上あるならdist_imageに探索画素をプロット
            if(255*4 <= sum(neighbour_points)):
                dist_image[x,y] = 255

    return dist_image

def neighbours(x, y, image):
    return [image[x-1][y], image[x-1][y+1], image[x][y+1], image[x+1][y+1], 
             image[x+1][y], image[x+1][y-1], image[x][y-1], image[x-1][y-1]]

def main():

    #エッジ画像をグレースケールで取得
    image = cv2.imread("canny1.png",0)

    #エッジ画像から4連結した画素のみを生成
    dist_image = count_neibor(image)

    cv2.imwrite("count_neibourhood.png", dist_image)
    cv2.imshow('input',image)
    cv2.imshow('dist_image',dist_image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()

 補足情報(FW/ツールのバージョンなど)

numpy  1.14.0
opencv 3.4.1
python 3.6.4

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

質問には『探索対象画素の周囲の9画素の内』と説明されていますが、コード中のneighbours関数は周囲の8画素のリストを返しています(基準となる画素(x,y)がリストに入っていません)

def neighbours(x, y, image):
    return [image[x-1][y], image[x-1][y+1], image[x][y+1], image[x+1][y+1], 
             image[x+1][y], image[x+1][y-1], image[x][y-1], image[x-1][y-1]]


def neighbours(x, y, image):
    return [image[x-1][y], image[x-1][y+1], image[x][y+1], image[x+1][y+1], 
             image[x+1][y], image[x+1][y-1], image[x][y-1], image[x-1][y-1], image[x],[y]]


と修正すべきだと思われます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/03 12:22

    ご解答ありがとうございます!
    早速修正します!

    キャンセル

0

coco_bauerさんの解答を参考にコードを修正致しました.
また,私の記述ミスで,『探索対象画素の周囲の9画素の内』は正しくは『探索対象画素の周囲の8画素の内』でした.

私のソースコードでは,エッジでない画素を注目している場合があったため,それが原因で,エッジの存在しない画素にプロットしていました.
問題が発生する例を以下の図1に示します.

_          イメージ説明
_                           図1 間違ってプロットする場合

図1では,中央の画素を探索画素としたとき,白をエッジ画像,灰色をエッジ以外の画像としています.この場合,修正前のソースコードでは,中央がエッジ以外の画像にも関わらず,処理が通るので,エッジのない画素にもプロットしていました.

修正後のソースコードを以下に示します.

import cv2
import numpy as np

def count_neibor(binary_image):
    image_thinned = binary_image.copy()
    #画像の縦と横のサイズを取得
    rows, columns = image_thinned.shape
    #プロットする画像を宣言
    dist_image = np.zeros(image_thinned.shape,dtype=np.uint8)

    #各画素を探索
    for x in range(1, rows - 1):
        for y in range(1, columns -1):

            #探索画素からエッジの画素のみを処理
            if(image_thinned[x,y] == 255):
                neighbour_points = neighbours(x, y, image_thinned)
                #近傍画素にエッジが3個のみならdist_imageに探索画素をプロット
                if(255*3 == sum(neighbour_points)):
                    dist_image[x,y] = 255

    return dist_image

def neighbours(x, y, image):
    return [image[x-1][y], image[x-1][y+1], image[x][y+1], image[x+1][y+1], 
             image[x+1][y], image[x+1][y-1], image[x][y-1], image[x-1][y-1]]

def main():

    #エッジ画像をグレースケールで取得
    image = cv2.imread("canny1.png",0)

    #エッジ画像から4連結した画素のみを生成
    dist_image = count_neibor(image)

    cv2.imwrite("count_neibourhood.png", dist_image)
    cv2.imshow('input',image)
    cv2.imshow('dist_image',dist_image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()

とすることで,無事に解決致しました.coco_bauerさん,多大なご助力ありがとうございました!

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.54%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Python 3.x

    6297questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • OpenCV

    1063questions

    OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。