Skip to content

Instantly share code, notes, and snippets.

@especialkim
Created April 6, 2024 16:16
Show Gist options
  • Save especialkim/b5e4323db751008c0ed7e77cfe4dbbda to your computer and use it in GitHub Desktop.
Save especialkim/b5e4323db751008c0ed7e77cfe4dbbda to your computer and use it in GitHub Desktop.
서지메모 아토믹화
import cv2
import numpy as np
import os
import datetime
from tkinter import Tk
from tkinter import filedialog
from tkinter.filedialog import askopenfilenames
from tkinter import simpledialog
def find_largest_contour(image_path):
# 이미지를 불러온다
image = cv2.imread(image_path)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV) # 테두리가 검은색인 이미지에 적합한 임계값
# 윤곽을 찾는다
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 가장 큰 윤곽을 찾는다
largest_contour = max(contours, key=cv2.contourArea)
return largest_contour, image
def crop_image_to_largest_contour_with_margin(image_path, output_dir):
largest_contour, image = find_largest_contour(image_path)
# 윤곽으로 이미지를 자른다
x, y, w, h = cv2.boundingRect(largest_contour)
cropped_image = image[y:y+h, x:x+w]
# DPI를 기준으로 0.5mm에 해당하는 픽셀 수를 계산한다.
dpi = 300
margin_mm = 1
margin_pixels = int((margin_mm/25.4) * dpi)
# 방금 계산한 마진을 적용하여 이미지를 더 작게 크롭한다.
cropped_image_with_margin = cropped_image[margin_pixels:-margin_pixels, margin_pixels:-margin_pixels]
# 이미지를 저장한다
if not os.path.exists(output_dir):
os.makedirs(output_dir)
filename = os.path.basename(image_path)
output_path_with_margin = os.path.join(output_dir, f"{filename}")
cv2.imwrite(output_path_with_margin, cropped_image_with_margin)
return output_path_with_margin
def split_image_into_tiles(image_path, output_dir, rows, cols):
# 이미지를 불러온다
image = cv2.imread(image_path)
height, width, _ = image.shape
# 각 타일의 크기를 계산한다
M, N = height // rows, width // cols
# 이미지를 가로 세로로 등분한다
for i in range(rows):
for j in range(cols):
tile = image[i*M:(i+1)*M, j*N:(j+1)*N]
# 타일을 저장한다
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# 파일명 생성: 기존 파일명에 _{알파벳}을 추가한다.
filename = os.path.basename(image_path)
file_root, file_ext = os.path.splitext(filename)
tile_filename = f"{file_root}_{chr(97 + i*cols + j)}{file_ext}"
cv2.imwrite(os.path.join(output_dir, tile_filename), tile)
def process_images(image_paths, output_dir):
for image_path in image_paths:
# 이미지 크롭 및 마진 추가
cropped_image_path_with_margin = crop_image_to_largest_contour_with_margin(image_path, output_dir)
# 이미지를 4x4로 분할
split_image_into_tiles(cropped_image_path_with_margin, output_dir, 4, 4)
# 파일 선택 다이얼로그를 표시한다
Tk().withdraw()
image_paths = filedialog.askopenfilenames(initialdir="/Users/yongminkim/Workspace/Scan") # 사용자가 여러 파일을 선택할 수 있는 다이얼로그를 열어준다
# 사용자에게 하위 폴더명을 입력받기
user_input = simpledialog.askstring("Input", "Enter subfolder name:")
# 현재 날짜 가져오기
today = datetime.datetime.now().strftime('%Y-%m-%d')
# 출력 루트 폴더 설정
output_root_folder = '/Users/yongminkim/Workspace/Obsidian/Lucy Vault/1 Inbox/10 System/10.01 Scan/'
# 최종 폴더명 생성 및 최종 경로 결합
final_folder_name = f"{today} {user_input}"
output_dir = os.path.join(output_root_folder, final_folder_name)
# 폴더가 없으면 생성
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# 모든 선택된 이미지를 처리한다
process_images(image_paths, output_dir)
@especialkim
Copy link
Author

MAC OS 에서 동작 확인하였습니다.

80번, 89번 경로를 수정해서 사용하세요.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment