Open CVで表からセルを認識してPyQt5のQGraphicsViewに認識結果を表示してみた

Share on:

Open CVを使って表が書かれている画像からセルを認識して、PyQt5のQGraphicsViewにセルの領域やセルに含まれる文字列の領域を表示して、QTableViewにセルごとの画像を表示するプログラムを作成しました。

画像を開く

Open filesをクリックしてファイルを選択すると画像を読み込み、テーブルのセルをクリックすると読み込んだ画像が表示されます。

読み込みはQtGui.QPixmapで読み込んでいます。

1QtGui.QPixmap(filename)

セルの認識の確認

Recognitionをクリックすると表の認識を実行して認識結果が表示されます。セルとして認識したエリアは赤枠で表示され、右のリストのBackやNextで認識した個所を確認できます。また、リストのアイテムをクリックすることでも認識エリアに赤枠が表示されます。

cv2.imread()で作成したcv2画像からcv2.Canny()でエッジ画像を作成して、cv2.findContours()でエッジ画像から輪郭を抽出して、cv2.approxPolyDP()で輪郭を近似ポリゴンに変換してセルを認識します。セルは四角形なのでcv2.approxPolyDP()で得られたポリゴンの点が4個なら四角形という判定を行っています。四角形の座標x, yと縦横の大きさw, hは下記コードのx, y, w, hの通りです。

 1cv2_image = cv2.imread( str(filename) )
 2gray = cv2.cvtColor(cv2_image, cv2.COLOR_BGR2GRAY)
 3edge = cv2.Canny(gray, 1, 100, apertureSize=3)
 4kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
 5edge = cv2.dilate(edge, kernel)
 6
 7contours, hierarchy = cv2.findContours(edge, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
 8
 9approxes = []
10for contour, hierarchy in zip(contours, hierarchy[0]):
11
12    area = cv2.contourArea(contour)
13    if not area_range[0] < area < area_range[1]:
14        continue
15
16    approx = cv2.approxPolyDP(contour, 0.01*cv2.arcLength(contour, True), True)
17    if len(approx) == 4:
18        approxes.append(approx)
19        
20rects, crops, crop_images = [], [], []
21for approx in approxes:
22
23    p1, p3 = approx[0][0], approx[2][0]
24    x, y = p1[0], p1[1]
25    w, h = p3[0] - p1[0], p3[1] - p1[1]
26    rect =  [x, y, w, h]

認識内容の確認

Edgeをチェックするとセルの領域認識用に作成したエッジ検出した画像が表示されます。Detect rectをチェックするとセルとして認識したエリアを全て青枠で表示して、Crop rectをチェックするとセル内にある文字を認識したエリアを緑枠で表示します。

セル認識の設定

contour_area_rangeを調整して、セルとして認識される四角形の面積を制限することができるようにしました。この面積の判定で表の大外といった大きすぎる四角形や、文字の中に含まれる小さすぎる四角形などを除外できます。

セルを分割してテーブルに表示する

Recognitionをクリックしてテーブルの認識を行った後にSplit cellsをクリックすると、クロップされた画像がテーブルに表示されます。

ソースコード

githubにアップロードしました

関連記事