ようやく新しいパソコン(macbook Air M1)で開発できるようになりました。別の用事などもあり、2週間もかかってしまいました。
肝心のkindle OCRアプリを作っていきます。
・kindleで選択した範囲を取得or除外します
kindle書籍でテキストファイルを抽出するアプリケーションを作っています。
kindle書籍にはイラストがあります。
そのイラストの箇所を読み取ってしまうと正常にOCR処理が行えません。
そこで、カーソル選択で文章やイラストを選択し、そのグレーで囲われた箇所を塗りつぶすことにしました。
しかし、囲われた箇所を白く塗りつぶそうとしましたが、完全に囲われていないと塗りつぶすことができませんでした。
ある程度のファジーさを許容するようにしても、完全な白で囲われている箇所があり塗りつぶせません。
import cv2
import numpy as np
def fill_tall_gray_areas(image_path, output_path, threshold_height=100, kernel_size=(5,5)):
# 画像を読み込む
image = cv2.imread(image_path)
# RGBでR:200, G:200, B:200の近傍をマスクとして取得
lower_bound = np.array([190, 190, 190])
upper_bound = np.array([210, 210, 210])
mask = cv2.inRange(image, lower_bound, upper_bound)
# モルフォロジー変換で小さな隙間を埋める
kernel = np.ones(kernel_size, np.uint8)
closed_mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
# 輪郭を検出する
contours, _ = cv2.findContours(closed_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 一定の高さ以上の領域とその中身を白で塗りつぶす
for contour in contours:
_, y, _, h = cv2.boundingRect(contour)
if h >= threshold_height:
cv2.drawContours(image, [contour], 0, (255, 255, 255), -1)
# 画像を保存
cv2.imwrite(output_path, image)
# 使用例
image_path = "/Users/user/Dropbox/python/csv_files/screenshot/processing/スクリーンショット 2023-10-14 18.27.34.png"
output_path = "/Users/user/Dropbox/python/csv_files/screenshot/processing/スクリーンショット 2023-10-14 18.27.34_w.png"
fill_tall_gray_areas(image_path, output_path)
そこで逆の発送で、文字をグレーで囲われた部分から、高さの値が小さいことを条件に抽出しようとしたが、それだとグレーで囲われた広範囲のイラストも、高さを小さく区切って抽出してしまい、失敗しました。
・長方形の4点を取得する
そのため、今度はグレーで囲われた箇所の輪郭を検出するときの座標を確認することにしました。
座標を取得し、その4点で囲われた箇所を白く塗りつぶすようにします。
実際試したら意図するように、イラストを塗りつぶすコードが完成しました。
import cv2
import numpy as np
def fill_tall_gray_areas(image_path, output_path, threshold_height=100):
# 画像を読み込む
image = cv2.imread(image_path)
# RGBでR:200, G:200, B:200の近傍をマスクとして取得
lower_bound = np.array([190, 190, 190])
upper_bound = np.array([210, 210, 210])
mask = cv2.inRange(image, lower_bound, upper_bound)
# 輪郭を検出する
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 一定の高さ以上の輪郭の領域を白く塗りつぶす
for i, contour in enumerate(contours):
# 輪郭の領域の左上、左下、右上、右下の座標を計算
x, y, w, h = cv2.boundingRect(contour)
if h >= threshold_height:
# 領域を白く塗りつぶす
cv2.rectangle(image, (x, y), (x+w, y+h), (255, 255, 255), -1)
print(f"Contour {i} filled:")
print(f"Left-Top: (x: {x}, y: {y})")
print(f"Left-Bottom: (x: {x}, y: {y+h})")
print(f"Right-Top: (x: {x+w}, y: {y})")
print(f"Right-Bottom: (x: {x+w}, y: {y+h})")
print("------")
# 画像を保存
cv2.imwrite(output_path, image)
これで、kindleのイラストを除外する目処が立ちました。