画像処理:スキャンした画像を多くの同一機能を備えたテンプレート画像にマッピングする

it_guy

問題の説明

スキャンした画像をテンプレート画像に一致させようとしています。

  • スキャンした画像の例:

スキャンした画像の例

  • テンプレート画像の例:

テンプレート画像の例

テンプレート画像には、サイズと輪郭のプロパティ(閉じた、左に開いた、右に開いた)が異なるハートのコレクションが含まれています。テンプレート内の各ハートは、場所、サイズ、輪郭の種類がわかっている関心領域です。私たちの目標は、スキャンした画像からこれらのROIを抽出できるように、スキャンしたものをテンプレートに一致させることです。スキャンされた画像では、これらのハートの一部が交差しており、交差しているかどうかを判断する分類子に提示されます。

私たちのアプローチ

Following a tutorial on PyImageSearch, we have attempted to use ORB to find matching keypoints (code included below). This should allow us to compute a perspective transform matrix that maps the scanned image on the template image.

We have tried some preprocessing steps such as thresholding and/or blurring the scanned image. We have also tried to increase the maximum number of features as much as possible.

The problem

The method fails to work for our image set. This can be seen in the following image: 次の画像で It appears that a lot of keypoints are mapped to the wrong part of the template image, so the transform matrix is not calculated correctly.

Is ORB the right technique to use here, or are there parameters of the algorithm that could be fine-tuned to improve performance? It feels like we are missing out on something simple that should make it work, but we really don't know how to go forward with this approach :).

We are trying out an alternative technique where we cross-correlate the scan with individual heart shapes. This should give an image with peaks at the heart locations. By drawing a bounding box around these peaks we hope to map that bounding box on the bounding box of the template (I can elaborat on this upon request)

Any suggestions are greatly appreciated!

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np


# Preprocessing parameters
THRESHOLD = True
BLUR      = False

# ORB parameters
MAX_FEATURES = 4048
KEEP_PERCENT = .01
SHOW_DEBUG = True

# Convert both the input image and template to grayscale
scan_file = r'scan.jpg'
template_file = r'template.jpg'

scan     = cv.imread(scan_file)
template = cv.imread(template_file)

scan_gray     = cv.cvtColor(scan, cv.COLOR_BGR2GRAY)
template_gray = cv.cvtColor(template, cv.COLOR_BGR2GRAY)

if THRESHOLD:
    _,  scan_gray     = cv.threshold(scan_gray, 127, 255, cv.THRESH_BINARY)
    _, template_gray  = cv.threshold(template_gray, 127, 255, cv.THRESH_BINARY)
    
if BLUR:
    scan_gray = cv.blur(scan_gray, (5, 5))
    template_gray = cv.blur(template_gray, (5, 5))

# Use ORB to detect keypoints and extract (binary) local invariant features
orb = cv.ORB_create(MAX_FEATURES)

(kps_template, desc_template) = orb.detectAndCompute(template_gray, None)
(kps_scan, desc_scan)         = orb.detectAndCompute(scan_gray, None)

# Match the features
#method  = cv.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING
#matcher = cv.DescriptorMatcher_create(method)
#matches = matcher.match(desc_scan, desc_template)
bf = cv.BFMatcher(cv.NORM_HAMMING)
matches = bf.match(desc_scan, desc_template)

# Sort the matches by their distances
matches = sorted(matches, key = lambda x : x.distance)

# Keep only the top matches
keep = int(len(matches) * KEEP_PERCENT)
matches = matches[:keep]


if SHOW_DEBUG:
    matched_visualization = cv.drawMatches(scan, kps_scan, template, kps_template, matches, None)
    plt.imshow(matched_visualization)
GaneshTata

Based on the clarifications provided by @it_guy, I have attempted to find all the crossed hearts using just the scanned image. I would have to try the algorithm on more images to check whether this approach will generalize or not.

  1. Binarize the scanned image.

    gray_image = cv2.cvtColor(rgb_image, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(gray_image, 180, 255, cv2.THRESH_BINARY_INV)
    

ここに画像の説明を入力してください

  1. Perform dilation to close small gaps in the outline of the hearts, and the curves representing crosses. Note - The structuring element np.ones((1,2), np.uint8 can be changed by running the algorithm through multiple images and finding the most suitable structuring element.
closing_original = cv2.morphologyEx(original_binary, cv2.MORPH_DILATE, np.ones((1,2), np.uint8)). 

ここに画像の説明を入力してください

  1. Find all the contours in the image. The contours include all hearts and the triangle at the bottom. We eliminate other contours like dots by placing constraints on the height and width of contours to filter them. Further, we also use contour hierachies to eliminate inner contours in cross hearts.
contours_original, hierarchy_original = cv2.findContours(closing_original, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)

ここに画像の説明を入力してください

  1. We iterate through each of the filtered contours.

Contour with normal heart -

ここに画像の説明を入力してください

Contour with crossed heart -

ここに画像の説明を入力してください

Let us observe the difference between these two types of hearts. If we look at the transition from white-to-black pixel and black-to-white pixel ( from top to bottom ) inside the normal heart, we see that for majority of the image columns the number of such transitions are 4. ( Top border - 2 transitions, bottom border - 2 transitions )

white-to-black pixel - (255, 255, 0, 0, 0)

黒から白へのピクセル- (0、0、255、255、255)

ただし、交差した心臓の場合、交差した曲線/線が心臓内にさらに2つの遷移(最初に黒から白、次に白から黒)を追加するため、大部分の列の遷移の数は6でなければなりません。 )。したがって、そのような遷移が4つ以上あるすべての画像列の中で、列の40%以上に6つの遷移がある場合、指定された輪郭は交差した輪郭を表します。結果-

ここに画像の説明を入力してください

コード-

import cv2
import numpy as np

def convert_to_binary(rgb_image):
    gray_image = cv2.cvtColor(rgb_image, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(gray_image, 180, 255, cv2.THRESH_BINARY_INV)
    return gray_image, thresh

original = cv2.imread('original.jpg')
height, width = original.shape[:2]
original_gray, original_binary = convert_to_binary(original) # Get binary image
cv2.imwrite("binary.jpg", original_binary)
closing_original = cv2.morphologyEx(original_binary, cv2.MORPH_DILATE, np.ones((1,2), np.uint8)) # Close small gaps in the binary image
cv2.imwrite("closed.jpg", closing_original)
contours_original, hierarchy_original = cv2.findContours(closing_original, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) # Get all the contours
bounding_rects_original = [cv2.boundingRect(c) for c in contours_original] # Get all contour bounding boxes
orig_boxes = list()

all_contour_image = original.copy()
for i, (x, y, w, h) in enumerate(bounding_rects_original):
    if h > height / 2 or w > width / 2:  # Eliminate extremely large contours
        continue
    if h < w / 2 or w < h / 2: # Eliminate vertical / horuzontal lines
        continue
    if w * h < 200: # Eliminate small area contours
        continue
    if hierarchy_original[0][i][3] != -1: # Eliminate contours created by heart crosses
        continue
    orig_boxes.append((x, y, w, h))
    cv2.rectangle(all_contour_image, (x,y), (x + w, y + h), (0, 255, 0), 3)
# cv2.imshow("warped", closing_original)
cv2.imwrite("all_contours.jpg", all_contour_image)

final_image = original.copy()
for x, y, w, h in orig_boxes:
    cropped_image = closing_original[y - 2 :y + h + 2, x: x + w] # Get the heart binary image

    col_pixel_diffs = np.abs(np.diff(cropped_image.T.astype(np.int16))/255) # Obtain all consecutive pixel differences in all the columns 

    column_sums = np.sum(col_pixel_diffs, axis=1) # Get the sum of each column's transitions. This results in an array of size equal 
    # to the number of columns, each element representing the number of black-white and white-black transitions. 

    percent_crosses = np.sum(column_sums >= 6)/ np.sum(column_sums >= 4) # Percentage of columns with 6 transitions among columns with 4 transitions
    if percent_crosses > 0.4: # Crossed heart criterion
        cv2.rectangle(final_image, (x,y), (x + w, y + h), (0, 255, 0), 3)
        cv2.imwrite("crossed_heart.jpg", cropped_image)
    else:
        cv2.imwrite("normal_heart.jpg", cropped_image)
cv2.imwrite("all_crossed_hearts.jpg", final_image)

このアプローチは、より多くの画像でテストして、その精度を見つけることができます。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Python OCR:スキャンした画像を処理用のテキストに変換する

分類Dev

画像をロードするためのテキストボックスでのイベント処理

分類Dev

キャンバスの描画をビットマップ画像に保存したい

分類Dev

補間された画像値をマッピングするために for ループの代わりに論理インデックスを使用する方法は?

分類Dev

Androidを使用した画像のキャプチャに関する画像のトリミングの問題

分類Dev

画像ではなくキャンバスに対してドラッグ可能な回転したキャンバス画像の処理

分類Dev

テキスト機能を備えたシンプルなjquery画像エディタ

分類Dev

正しく機能しないキャンバスを使用して画像を1つにマージする

分類Dev

デザインプレビュー機能を備えたResourceDictionaryにXAML画像を含める

分類Dev

キャンバスの円(青い円)の中心にビットマップ画像(ピン)を配置する方法は?

分類Dev

マルチプロセッシングを使用した画像の前処理

分類Dev

Html Canvasは、レンダリングされた画像にテキストまたは画像を追加します

分類Dev

コマンドラインのffmpegまたはopencvを介してIPカメラから画像をキャプチャし、グレー画像を取得します

分類Dev

上記のソース画像の処理から得られたキャニーエッジアウトラインに基づくopencvでのソース画像のセグメンテーション

分類Dev

マークダウンとパンドックを使用したHTMLのテキスト/画像の中央揃え

分類Dev

キャンバスを使用して画像の一部を透明にするためにアルファレイヤーマスクを適用する方法

分類Dev

OpenCVとPythonを使用したビデオストリーミングで、ビデオの画像をフレームごとに処理する方法

分類Dev

Pythonのグレースケールヒートマップからマルチカラーのしきい値処理された画像を作成する

分類Dev

比率をリセットした後、キャンバス内の画像を再スケーリングします

分類Dev

SCNNodeを非表示にしてSCNViewの画像/スクリーンショットをキャプチャする:drawViewHierarchyInRectafterScreenUpdatesが機能しない

分類Dev

グローバルメモリのロード/ストアは、コンピューティング機能1.xを備えたデバイスのキャッシュを通過しますか?

分類Dev

OpenCV-エンボス文字(クレジットカード、プレート番号など)をよりよく読み取るための画像処理技術

分類Dev

ファックスのように見えるドキュメントの画像をバッチ処理する

分類Dev

トレーニングプロセス中に処理された画像の数を知る方法はありますか?

分類Dev

forループの画像マスキングをPythonの論理インデックスに置き換えるにはどうすればよいですか?

分類Dev

キャレットを使用したトレーニングおよびテストデータの前処理

分類Dev

画像とテキストの間にスペースまたはマージンを与える方法

分類Dev

GraphQLを使用したGatsbyギャラリー画像のマッピング

分類Dev

GraphQLを使用したGatsbyギャラリー画像のマッピング

Related 関連記事

  1. 1

    Python OCR:スキャンした画像を処理用のテキストに変換する

  2. 2

    画像をロードするためのテキストボックスでのイベント処理

  3. 3

    キャンバスの描画をビットマップ画像に保存したい

  4. 4

    補間された画像値をマッピングするために for ループの代わりに論理インデックスを使用する方法は?

  5. 5

    Androidを使用した画像のキャプチャに関する画像のトリミングの問題

  6. 6

    画像ではなくキャンバスに対してドラッグ可能な回転したキャンバス画像の処理

  7. 7

    テキスト機能を備えたシンプルなjquery画像エディタ

  8. 8

    正しく機能しないキャンバスを使用して画像を1つにマージする

  9. 9

    デザインプレビュー機能を備えたResourceDictionaryにXAML画像を含める

  10. 10

    キャンバスの円(青い円)の中心にビットマップ画像(ピン)を配置する方法は?

  11. 11

    マルチプロセッシングを使用した画像の前処理

  12. 12

    Html Canvasは、レンダリングされた画像にテキストまたは画像を追加します

  13. 13

    コマンドラインのffmpegまたはopencvを介してIPカメラから画像をキャプチャし、グレー画像を取得します

  14. 14

    上記のソース画像の処理から得られたキャニーエッジアウトラインに基づくopencvでのソース画像のセグメンテーション

  15. 15

    マークダウンとパンドックを使用したHTMLのテキスト/画像の中央揃え

  16. 16

    キャンバスを使用して画像の一部を透明にするためにアルファレイヤーマスクを適用する方法

  17. 17

    OpenCVとPythonを使用したビデオストリーミングで、ビデオの画像をフレームごとに処理する方法

  18. 18

    Pythonのグレースケールヒートマップからマルチカラーのしきい値処理された画像を作成する

  19. 19

    比率をリセットした後、キャンバス内の画像を再スケーリングします

  20. 20

    SCNNodeを非表示にしてSCNViewの画像/スクリーンショットをキャプチャする:drawViewHierarchyInRectafterScreenUpdatesが機能しない

  21. 21

    グローバルメモリのロード/ストアは、コンピューティング機能1.xを備えたデバイスのキャッシュを通過しますか?

  22. 22

    OpenCV-エンボス文字(クレジットカード、プレート番号など)をよりよく読み取るための画像処理技術

  23. 23

    ファックスのように見えるドキュメントの画像をバッチ処理する

  24. 24

    トレーニングプロセス中に処理された画像の数を知る方法はありますか?

  25. 25

    forループの画像マスキングをPythonの論理インデックスに置き換えるにはどうすればよいですか?

  26. 26

    キャレットを使用したトレーニングおよびテストデータの前処理

  27. 27

    画像とテキストの間にスペースまたはマージンを与える方法

  28. 28

    GraphQLを使用したGatsbyギャラリー画像のマッピング

  29. 29

    GraphQLを使用したGatsbyギャラリー画像のマッピング

ホットタグ

アーカイブ