付箋画像の抽出を試してみた(まだうまくいってない)
ホワイトボードの写真から付箋画像を抽出したいって話を聞いて
それOpenCVでできるんじゃないかと一生懸命ググってみました。
以下記事を参考に 試しにやってみた記録です。 qiita.com www.blog.umentu.work
環境
Dockerコンテナ (https://hub.docker.com/r/moremagic/jupyter/)
- Ubuntu + OpenCV3.4 + Python3 + jupyter
- Opencv3.1 から 3.4 にVersionをあげるのが大変だった
まず画像を表示してみる
%matplotlib inline import cv2 # opencv import matplotlib.pyplot as plt # matplotlibの描画系 fn_img = "test.jpeg" # 画像ファイル名 img = cv2.imread(fn_img) # 画像を読み込む # opencvの処理系では (B,G,R) で管理されているが、 # matplotlib では (R,G,B) で画像を認識するので、 # 表示用に一旦変換する show_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(show_img) #表示
- 付箋を抽出してみる
# 画像差分を算出 def createDiffImg(img, base_img): img_diff = cv2.absdiff(base_img, img) return cv2.threshold(img_diff, 20, 255, cv2.THRESH_BINARY)[1] # 差分を二値化 def show_hoge(img_diff): return cv2.threshold(img_diff, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1] im_gray = cv2.cvtColor(show_img, cv2.COLOR_BGR2GRAY) # 元画像を RGBに分割 RGB =cv2.split(show_img) Blue = show_hoge(createDiffImg(RGB[0], im_gray)) Green = show_hoge(createDiffImg(RGB[1], im_gray)) Red = show_hoge(createDiffImg(RGB[2], im_gray)) #plt.imshow( Green ) aaa = cv2.addWeighted(Blue,0.5,Green,0.5,0) aaa = cv2.addWeighted(aaa,0.5,Red,0.5,0) plt.imshow( aaa )
- 画像を切り出してみる
def getRectByPoints(points): # prepare simple array points = list(map(lambda x: x[0], points)) points = sorted(points, key=lambda x:x[1]) top_points = sorted(points[:2], key=lambda x:x[0]) bottom_points = sorted(points[2:4], key=lambda x:x[0]) points = top_points + bottom_points left = min(points[0][0], points[2][0]) right = max(points[1][0], points[3][0]) top = min(points[0][1], points[1][1]) bottom = max(points[2][1], points[3][1]) return (top, bottom, left, right) def getPartImageByRect(rect, img): return img[rect[0]:rect[1], rect[2]:rect[3]] contours = cv2.findContours(aaa, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[1] # filtered with area over (all area / 100 ) th_area = aaa.shape[0] * aaa.shape[1] / 100 contours_large = list(filter(lambda c:cv2.contourArea(c) > th_area, contours)) outputs = [] rects = [] approxes = [] for (i,cnt) in enumerate(contours_large): arclen = cv2.arcLength(cnt, True) approx = cv2.approxPolyDP(cnt, 0.02*arclen, True) if len(approx) < 4: continue approxes.append(approx) rect = getRectByPoints(approx) rects.append(rect) outputs.append(getPartImageByRect(rect, show_img)) cv2.imwrite(str(i)+'.jpg', getPartImageByRect(rect, show_img))
結果
付箋を四角く フィルタをかけることはできたっぽいですが
二値画像にした(つもり)なのに なんか超黄色くなってるし
一部しか抽出できませんでした・・・orz
もうちょっとちゃんと勉強してみないとだめっぽいです。
※ 続くかも
moremagic
2018-02-25