inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

OpenCV 를 활용한 명함인식 기능 구현 강좌

강의 자료

강의 마지막 예제에서 다음과 같은 에러가 발생합니다.

9223

gaeggol

작성한 질문수 2

0

images/scannedImage.png only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices

코드는 아래와 같습니다.

# (참고) OpenCV - 이미지에서 텍스트 영역만 찾아내기 # 출처: http://www.danvk.org/2015/01/07/finding-blocks-of-text-in-an-image-using-python-opencv-and-numpy.html import glob import os import random import sys import random import math import json from collections import defaultdict import cv2 from PIL import Image, ImageDraw import numpy as np from scipy.ndimage.filters import rank_filter def dilate(ary, N, iterations): """Dilate using an NxN '+' sign shape. ary is np.uint8.""" kernel = np.zeros((N,N), dtype=np.uint8) kernel[(N-1)/2,:] = 1 dilated_image = cv2.dilate(ary / 255, kernel, iterations=iterations) kernel = np.zeros((N,N), dtype=np.uint8) kernel[:,(N-1)/2] = 1 dilated_image = cv2.dilate(dilated_image, kernel, iterations=iterations) dilated_image = cv2.convertScaleAbs(dilated_image) return dilated_image def props_for_contours(contours, ary): """Calculate bounding box & the number of set pixels for each contour.""" c_info = [] for c in contours: x,y,w,h = cv2.boundingRect(c) c_im = np.zeros(ary.shape) cv2.drawContours(c_im, [c], 0, 255, -1) c_info.append({ 'x1': x, 'y1': y, 'x2': x + w - 1, 'y2': y + h - 1, 'sum': np.sum(ary * (c_im > 0))/255 }) return c_info def union_crops(crop1, crop2): """Union two (x1, y1, x2, y2) rects.""" x11, y11, x21, y21 = crop1 x12, y12, x22, y22 = crop2 return min(x11, x12), min(y11, y12), max(x21, x22), max(y21, y22) def intersect_crops(crop1, crop2): x11, y11, x21, y21 = crop1 x12, y12, x22, y22 = crop2 return max(x11, x12), max(y11, y12), min(x21, x22), min(y21, y22) def crop_area(crop): x1, y1, x2, y2 = crop return max(0, x2 - x1) * max(0, y2 - y1) def find_border_components(contours, ary): borders = [] area = ary.shape[0] * ary.shape[1] for i, c in enumerate(contours): x,y,w,h = cv2.boundingRect(c) if w * h > 0.5 * area: borders.append((i, x, y, x + w - 1, y + h - 1)) return borders def angle_from_right(deg): return min(deg % 90, 90 - (deg % 90)) def remove_border(contour, ary): """Remove everything outside a border contour.""" # Use a rotated rectangle (should be a good approximation of a border). # If it's far from a right angle, it's probably two sides of a border and # we should use the bounding box instead. c_im = np.zeros(ary.shape) r = cv2.minAreaRect(contour) degs = r[2] if angle_from_right(degs) <= 10: box = cv2.boxPoints(r) box = np.int0(box) cv2.drawContours(c_im, [box], 0, 255, -1) cv2.drawContours(c_im, [box], 0, 0, 4) else: x1, y1, x2, y2 = cv2.boundingRect(contour) cv2.rectangle(c_im, (x1, y1), (x2, y2), 255, -1) cv2.rectangle(c_im, (x1, y1), (x2, y2), 0, 4) return np.minimum(c_im, ary) def find_components(edges, max_components=16): """Dilate the image until there are just a few connected components. Returns contours for these components.""" # Perform increasingly aggressive dilation until there are just a few # connected components. count = 21 dilation = 5 n = 1 while count > 16: n += 1 dilated_image = dilate(edges, N=3, iterations=n) #_, contours, hierarchy = cv2.findContours(dilated_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) contours, hierarchy = cv2.findContours(dilated_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) count = len(contours) #print dilation #Image.fromarray(edges).show() #Image.fromarray(255 * dilated_image).show() return contours def find_optimal_components_subset(contours, edges): """Find a crop which strikes a good balance of coverage/compactness. Returns an (x1, y1, x2, y2) tuple. """ c_info = props_for_contours(contours, edges) c_info.sort(key=lambda x: -x['sum']) total = np.sum(edges) / 255 area = edges.shape[0] * edges.shape[1] c = c_info[0] del c_info[0] this_crop = c['x1'], c['y1'], c['x2'], c['y2'] crop = this_crop covered_sum = c['sum'] while covered_sum < total: changed = False recall = 1 * covered_sum / total prec = 1 - 1 * crop_area(crop) / area f1 = 2 * (prec * recall / (prec + recall)) #print '----' for i, c in enumerate(c_info): this_crop = c['x1'], c['y1'], c['x2'], c['y2'] new_crop = union_crops(crop, this_crop) new_sum = covered_sum + c['sum'] new_recall = 1 * new_sum / total new_prec = 1 - 1 * crop_area(new_crop) / area new_f1 = 2 * new_prec * new_recall / (new_prec + new_recall) # Add this crop if it improves f1 score, # _or_ it adds 25% of the remaining pixels for <15% crop expansion. # ^^^ very ad-hoc! make this smoother remaining_frac = c['sum'] / (total - covered_sum) new_area_frac = 1 * crop_area(new_crop) / crop_area(crop) - 1 if new_f1 > f1 or ( remaining_frac > 0.25 and new_area_frac < 0.15): print('%d %s -> %s / %s (%s), %s -> %s / %s (%s), %s -> %s' % ( i, covered_sum, new_sum, total, remaining_frac, crop_area(crop), crop_area(new_crop), area, new_area_frac, f1, new_f1)) crop = new_crop covered_sum = new_sum del c_info[i] changed = True break if not changed: break return crop def pad_crop(crop, contours, edges, border_contour, pad_px=15): """Slightly expand the crop to get full contours. This will expand to include any contours it currently intersects, but will not expand past a border. """ bx1, by1, bx2, by2 = 0, 0, edges.shape[0], edges.shape[1] if border_contour is not None and len(border_contour) > 0: c = props_for_contours([border_contour], edges)[0] bx1, by1, bx2, by2 = c['x1'] + 5, c['y1'] + 5, c['x2'] - 5, c['y2'] - 5 def crop_in_border(crop): x1, y1, x2, y2 = crop x1 = max(x1 - pad_px, bx1) y1 = max(y1 - pad_px, by1) x2 = min(x2 + pad_px, bx2) y2 = min(y2 + pad_px, by2) return crop crop = crop_in_border(crop) c_info = props_for_contours(contours, edges) changed = False for c in c_info: this_crop = c['x1'], c['y1'], c['x2'], c['y2'] this_area = crop_area(this_crop) int_area = crop_area(intersect_crops(crop, this_crop)) new_crop = crop_in_border(union_crops(crop, this_crop)) if 0 < int_area < this_area and crop != new_crop: print('%s -> %s' % (str(crop), str(new_crop))) changed = True crop = new_crop if changed: return pad_crop(crop, contours, edges, border_contour, pad_px) else: return crop def downscale_image(im, max_dim=2048): """Shrink im until its longest dimension is <= max_dim. Returns new_image, scale (where scale <= 1). """ a = im.shape[0] b = im.shape[1] if max(a, b) <= max_dim: return 1, im scale = 1 * max_dim / max(a, b) dim = (int(a * scale), int(b * scale)) new_im = cv2.resize(im, dim, interpolation = cv2.INTER_AREA) return scale, new_im def process_image(path, out_path): orig_im = Image.open(path) im = cv2.imread(path, cv2.IMREAD_GRAYSCALE) scale, im = downscale_image(im) edges = cv2.Canny(im, 100, 200) # TODO: dilate image _before_ finding a border. This is crazy sensitive! #_, contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) borders = find_border_components(contours, edges) borders.sort(key=lambda i_x1_y1_x2_y2: (i_x1_y1_x2_y2[3] - i_x1_y1_x2_y2[1]) * (i_x1_y1_x2_y2[4] - i_x1_y1_x2_y2[2])) border_contour = None if len(borders): border_contour = contours[borders[0][0]] edges = remove_border(border_contour, edges) edges = 255 * (edges > 0).astype(np.uint8) # Remove ~1px borders using a rank filter. maxed_rows = rank_filter(edges, -5, size=(1, 20)) maxed_cols = rank_filter(edges, -5, size=(20, 1)) debordered = np.minimum(np.minimum(edges, maxed_rows), maxed_cols) edges = debordered contours = find_components(edges) if len(contours) == 0: print('%s -> (no text!)' % path) return crop = find_optimal_components_subset(contours, edges) crop = pad_crop(crop, contours, edges, border_contour) crop = [int(x / scale) for x in crop] # upscale to the original image size. # draw and show cropped rectangle area in the original image rgb_im = orig_im.convert('RGB') draw = ImageDraw.Draw(rgb_im) draw.rectangle(crop, outline='red') rgb_im.show() text_im = orig_im.crop(crop) text_im.show() text_im.save(out_path) print('%s -> %s' % (path, out_path)) if __name__ == '__main__': # path = 'images/text.jpg' path = 'images/scannedImage.png' out_path = 'croppedImage.png' try: process_image(path, out_path) except Exception as e: print('%s %s' % (path, e))


컴퓨터-비전 딥러닝 opencv

답변 4

1

뉴럴웍스랩

문서원본:

https://www.danvk.org/2015/01/07/finding-blocks-of-text-in-an-image-using-python-opencv-and-numpy.html

테스트에 사용한 이미지 파일:

https://www.danvk.org/images/milstein-backing.jpg

1

뉴럴웍스랩

https://gist.github.com/luipillmann/d76eb4f4eea0320bb35dcd1b2a4575ee
여기 소스를 테스트해보니 잘 됩니다.

다만 opencv 버전 차이로 생기는 문제가 있으면 소스를 살짝 수정해야 합니다.

findContours()의 리턴값이 2개인지, 3개인지에 따라 수정 필요합니다.

findContours()가 두 군데 있습니다. 

이런 오류가 발생하면 findContours()의 리턴값이 2개이라는 의미로,   아래의 소스와 같이 수정 필요합니다.

ValueError: not enough values to unpack (expected 3, got 2)

수정 전 : #_, contours, hierarchy = cv2.findContours(dilated_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

수정 후:        contours, hierarchy = cv2.findContours(dilated_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

0

개foot

images/scannedImage.png only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices

이에러는

저기 kernel 에 나누는 / 슬러시를 더블 // 로 바꾸면 해결 되는거 확인했습니다.

0

김성현

저도 같은 오류가 발생하여 디버깅을 해봤는데요.. 오류 발생하는 곳을 찾긴했는데, 

dilate 함수 내용중에
kernel[(N - 1) / 2, :] = 1 이곳에서 Error가 발생하던데..

왜 발생하는지 이해가 안가네요..답변좀 부탁드립니다.

53초에 OpenCVSharp2.4.10 폴더를 찾고 있습니다.

0

37

1

침식 후 팽창을 해도 노이즈가 제거 안돼요

0

49

0

vs code에서 주피터 노트북 익스텐션 설치하고 써도 되나요?

0

96

1

맥에서 OpenCV 로 이미지 출력문제

0

135

1

카메라 출력 질문

0

99

1

설치문제

0

96

1

이미지 파일을 불러올 수 없다는 오류 메시지가 출력됩니다...ㅜㅜ

0

212

1

안녕하세요 맥 cuda 관련해서 질문 올립니다.

0

351

1

jupiter notebook에서 python gui 화면이 안 떠요 (자답 포함)

0

519

1

질문 및 버전에러

0

432

1

에러가 발생합니다.

0

258

0

명함인식

0

866

1

OpenCV - 스캔한 듯한 효과 주기 (1) 코드 실행 결과질문

0

410

0

# (참고) OpenCV - 이미지에서 텍스트 영역만 찾아내기

1

415

2

강의최종완성본소스코드를제공해주실수있을까요

0

384

3

ValueError가 뜹니다.

0

446

1

Anaconda prompt에서 opencv설치 시 오류가 뜹니다.

1

451

1

박스 클릭하고 Ctrl + return 버튼 클릭 시 메시지

0

272

1

라즈베리파이(라즈비안) Python2.7 OpenCV-3.4.3 환경에서 예제프로그램 사용.

0

461

1

TesseractNotFoundError 라고 뜹니다.

0

277

0

링크에러

0

203

0

OCR – Tesseract

0

453

1

소스코드 다운로드하여 압축해제하면 내용이 아무것도 없어요.

0

212

0

궁금합니다.

0

294

0