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

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

(19개의 수강평)

456명의 수강생
29,700원
지식공유자 · 마이캠퍼스
19회 수업 · 총 2시간 21분 수업
평생 무제한 시청
수료증 발급 강의
수강 난이도 '중급'
마이캠퍼스의 다른 강의
연관 로드맵
아직 다른 강의가 없어요 ㅠㅠ
연관 로드맵이 없어요 ㅠㅠ
백영민 프로필

강의 마지막 예제에서 다음과 같은 에러가 발생합니다. 백영민 24일 전

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))


0
조성은 프로필

Anaconda prompt에서 opencv설치 시 오류가 뜹니다. 조성은 8달 전

ERROR conda.core.link:_execute(507): An error occurred while uninstalling package 'defaults::conda-4.5.12-py27_0'.

WindowsError(5, '')

Attempting to roll back.

현재 파이썬이 3.6.8버전도 함께 깔려 있어서 이런 오류가 뜨는 것 같은데 어떻게 해결해야 할까요..?

1
ucopy R 프로필

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

박스 클릭하고 Ctrl + return 버튼 클릭 위와 같은 결과가 나오는 것을 확인을 실행했을 때 아래와 같이 실습준비설명서와 다른 메시지가 나옵니다.

File "", line 12

print "python:", sys.version

^

SyntaxError: Missing parentheses in call to 'print'. Did you mean print("python:", sys.version)?

0
정병태 프로필

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

이미지 읽고 쓰기 (1)의 문장을 제목과 같은 환경에서 사용을 시도하였습니다. 임시로 파일의 이름은 readimage1.py로 바꾼 상태로 터미널에서 사용하였습니다.

   File "readimage1.py", lin 14
      if__name__=='__main__':
                                                           ^
SyntaxError: invalid syntax</p>

라는 에러가 나와 (:)를 지우면

   File "readimage1.py", lin 14
       handle_image()
       ^
SyntaxError: invalid syntax</p>

라는 에러가 나옵니다. 또 아예 가려버리면 창이 뜨지를 않으니 굉장히 곤란한 상황입니다.

비록 강의에서 알려주신 환경은 윈도우였지만 라즈베리파이를 써야하는 상황이라 꼭 알려주시면 감사하겠습니다.

0
치킨내나 프로필

TesseractNotFoundError 라고 뜹니다. 치킨내나 2018.09.06

TesseractNotFoundError: tesseract is not installed or it's not in your path

이미지로부터 텍스트 추출인데 이렇게 뜨네요 저번에는 잘 됐는데 안됩니다 ㅜ

0
kwonsoo 프로필

링크에러 kwonsoo 2018.07.17

실습준비 설명서 16페이지 tesseract 링크 에러납니다.

마이크로 소프트 oxford 링크 에러납니다.

0
ujsong4 프로필

OCR – Tesseract ujsong4 2018.07.11

안녕하세요. 지금 강의를 듣고 있는데 윗부분들은 다 잘 됐는데 tesseract가 안먹어요ㅠㅠ

TesseractNotFoundErrorTraceback (most recent call last)

in ()
13
14 if name == 'main':
---> 15 ocr_tesseract()

in ocr_tesseract()
7 image_file = 'images/scannedImage.png'
8 im = Image.open(image_file)
----> 9 text = pytesseract.image_to_string(im) #이미지로부터 텍스트를 추출해 낼 수 있다.
10 im.show()
11

C:UsersLGAnaconda2libsite-packagespytesseractpytesseract.pyc in image_to_string(image, lang, config, nice, boxes, output_type)
284 return run_and_get_output(image, 'txt', lang, config, nice, True)
285
--> 286 return run_and_get_output(image, 'txt', lang, config, nice)
287
288

C:UsersLGAnaconda2libsite-packagespytesseractpytesseract.pyc in run_and_get_output(image, extension, lang, config, nice, return_bytes)
199 return output_file.read().decode('utf-8').strip()
200 except OSError:
--> 201 raise TesseractNotFoundError()
202 finally:
203 cleanup(temp_name)

TesseractNotFoundError: tesseract is not installed or it's not in your path

이렇게 뜨는데 무슨 문제가 있는 걸까요?

테스트코드에서도 경로 맞아서 테스트도 완료했는데 뭐가 문제인지 모르겠습니다ㅠㅠ
tesseract가 안돼서 project oxford로 하려고 했고 키값도 받았는데도 그것도 안먹고요...
인강에서 말씀하신 것 처럼 키값만 넣어주면 되는거 아닌가용? 도와주세여ㅠㅠㅠㅠ

1
알봉 프로필

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

안녕하세요.

소스코드를 다운받아서 압축해제하니 아무 것도 없네요.

빵집을 사용하는데, 압축해제하려고 더블클릭하면 폴더명이 모두 글자가 깨진채로 구성되어 있긴 합니다.

0
조원준 프로필

궁금합니다. 조원준 2017.10.02
무엇인지요? 설명에서는 없는데 if __name__ == '__main__': handel_image()

0
지식공유자 되기
많은 사람들에게 배움의 기회를 주고,
경제적 보상을 받아보세요.
지식공유참여
기업 교육을 위한 인프런
“인프런 비즈니스” 를 통해 모든 팀원이 인프런의 강의들을
자유롭게 학습하는 환경을 제공하세요.
인프런 비즈니스