디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

북스캔 파이썬 코드 퍼블릭 도메인 (1)

몬발켜갤로그로 이동합니다. 2024.04.30 12:37:03
조회 72 추천 1 댓글 0

<내가 chatGPT4랑 의논해서 만든 코드임... 다른 사람 코드는 전혀 들어있지 않음. 마음대로 쓰시라고 공개함.>


import cv2
import os
import numpy as np
import sys

folder_path = "C:/input" # 작업하려는 폴더 경로
file_list = os.listdir(folder_path)

image_extensions = [".jpg", ".jpeg", ".png"] # 그림 파일만 불러온다
image_files = [file for file in file_list if any(file.lower().endswith(ext) for ext in image_extensions)]

# 각 파일을 하나씩 불러온다
for image_name in image_files:

# 이미지 파일을 불러온다
image = cv2.imread("C:\\input\\{}".format(image_name))

# 그레이 스케일 및 이진화
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU )

# 컨투어 찾기
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 가장 큰 컨투어 찾기
largest_contour = max(contours, key=cv2.contourArea)

# 가장 큰 컨투어에 불필요한 점/점들이 포함된 경우가 종종 발생하기 때문에 제거할 필요가 있다
# 새로운 이미지 생성 (검은색 배경)
new_image = np.zeros_like(binary)

# 가장 큰 컨투어 중에서 면적이 가장 큰 폐곡선 찾기
largest_closed_contour = max([c for c in contours if cv2.contourArea(c) > 0], key=cv2.contourArea)

# 면적이 가장 큰 폐곡선 안에 있는 흰색 점들만 남기고 나머지는 삭제하여 새 이미지에 저장
cv2.drawContours(new_image, [largest_closed_contour], -1, (255), thickness=cv2.FILLED)

# 컨투어를 둘러싼 가장 작은 사각형 찾기
min_rect = cv2.minAreaRect(largest_closed_contour)

# minAreaRect에서 반환한 4개 점은 실수값을 갖으므로, 사용하려면 정수로 변환한다
box_points = cv2.boxPoints(min_rect)
box_points = np.intp(box_points)

# 4개 점을 좌표값에 따라서 번호를 부여한다
# 원래의 의도는 좌상, 우상, 좌하, 우하 순서로 P1, P2, P3, P4를 부여하려고 하였다
# 그러나 프로그래머의 일반적인 코드 규칙에 따라서 점의 번호를 부여하기로 생각을 바꿨다.
# The order will be P1 (top-left), P2 (top-right), P3 (bottom-left), P4 (bottom-right)
box_points = sorted(box_points, key=lambda x: (x[1], x[0]))
if box_points[0][0] > box_points[1][0]:
box_points[0], box_points[1] = box_points[1], box_points[0]
if box_points[2][0] > box_points[3][0]:
box_points[2], box_points[3] = box_points[3], box_points[2]

# 프로그래머의 일반적인 코드 부여 방법에 따라서 점의 번호를 정했다
P1 = box_points[0]
P2 = box_points[1]
P3 = box_points[2]
P4 = box_points[3]

if P1[0] < P2[0]: # 기울기가 양수일 때(왼쪽으로 기울었다:시계방향으로 회전해야 한다)
x1, y1 = P1[0], P1[1]
x2, y2 = P2[0], P2[1]

# 기울기 slope를 계산한다.
delta_x = x2 - x1
delta_y = y2 - y1
slope = delta_y / delta_x if delta_x != 0 else None

# 기울기에 따라서 회전할 각과 방향을 계산한다
# Calculate the angle in radians and then convert to degrees
# The angle must be negative for a clockwise rotation
angle_of_rotation = -np.degrees(np.arctan(slope))

# 시계방향으로 angle만큼 회전하고, 변수에 저장한다
# center에 들어갈 점 P의 좌표는 데이터형을 변환해야 한다
center = (int(P1[0]), int(P1[1]))
angle = -angle_of_rotation
M = cv2.getRotationMatrix2D(center, angle, 1)
rotated_image = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))

# 회전한 이미지를 저장하지 않고 변수를 바로 사용하여 다음 단계의 작업을 진행한다
#그레이 스케일 및 이진화
gray1 = cv2.cvtColor(rotated_image, cv2.COLOR_BGR2GRAY)
_, binary1 = cv2.threshold(gray1, 127, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU )

# 회전한 이미지의 컨투어 찾기
contours1, _ = cv2.findContours(binary1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 회전한 이미지의 가장 큰 컨투어 찾기
largest_contour1 = max(contours1, key=cv2.contourArea)

# 새로운 이미지 생성 (검은색 배경)
new_image1 = np.zeros_like(binary1)

# 가장 큰 컨투어에 불필요한 점/점들이 포함된 경우가 종종 발생하기 때문에 제거할 필요가 있다
# 회전한 이미지의 가장 큰 컨투어 중에서 면적이 가장 큰 폐곡선 찾기
largest_closed_contour1 = max([c for c in contours1 if cv2.contourArea(c) > 0], key=cv2.contourArea)

# 면적이 가장 큰 폐곡선 안에 있는 흰색 점들만 남기고 나머지는 삭제하여 새 이미지에 저장
cv2.drawContours(new_image1, [largest_closed_contour1], -1, (255), thickness=cv2.FILLED)

# 회전한 이미지의 컨투어를 포함하는 가장 작은 사각형을 찾는다
min_rect1 = cv2.minAreaRect(largest_closed_contour1)

# minAreaRect에서 반환한 4개 점은 실수값을 갖으므로, 사용하려면 정수로 변환한다
# Convert it to box points (four points)
box_points1 = cv2.boxPoints(min_rect1)
box_points1 = np.intp(box_points1)

# # 4개 점을 좌표값에 따라서 번호를 부여한다
# 원래의 의도는 좌상, 우상, 좌하, 우하 순서로 P1, P2, P3, P4를 부여하려고 하였다
# 그러나 프로그래머의 일반적인 코드 규칙에 따라서 점의 번호를 부여하기로 생각을 바꿨다.
# The order will be P1 (top-left), P2 (top-right), P3 (bottom-left), P4 (bottom-right)
box_points1 = sorted(box_points1, key=lambda x: (x[1], x[0]))
if box_points1[0][0] > box_points1[1][0]:
box_points1[0], box_points1[1] = box_points1[1], box_points1[0]
if box_points1[2][0] > box_points1[3][0]:
box_points1[2], box_points1[3] = box_points1[3], box_points1[2]

# 프로그래머의 일반적인 코드 부여 방법에 따라서 점의 번호를 정했다
# 점의 번호를 앞의 점과 다르게 해서 혼동을 피했다
P11 = box_points1[0]
P22 = box_points1[1]
P33 = box_points1[2]
P44 = box_points1[3]
# 4개 점의 좌표를 이용하여 사각형 영역을 택하여 새 그림 파일로 저장한다
k = rotated_image[P11[1]:P33[1], P11[0]:P22[0]]

cv2.imwrite("C:\\output\\{}".format(image_name), k)

else: # 기울기가 양수가 아닐 때(오른쪽으로 기울었다:반시계방향으로 회전해야 한다)

x1, y1 = P1[0], P1[1]
x2, y2 = P2[0], P2[1]

# 기울기를 계산한다
delta_x = x2 - x1
delta_y = y2 - y1
slope = delta_y / delta_x if delta_x != 0 else None

# 기울기에 따라서 회전할 각과 방향을 계산한다
# If the slope is zero (horizontal line), we do not need to rotate.
# If the slope is negative or undefined (vertical line), we rotate counterclockwise.
# The angle must be positive for a counterclockwise rotation
angle_of_rotation = np.degrees(np.arctan(-slope)) if slope is not None else 90

# 반시계방향으로 angle만큼 회전하여 변수에 저장한다
# center에 들어갈 점 P의 좌표는 데이터형을 변환해야 한다
center = (int(P1[0]), int(P1[1]))
angle = angle_of_rotation
M = cv2.getRotationMatrix2D(center, angle, 1)
rotated_image = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))

# 회전한 이미지를 저장하지 않고 변수를 바로 사용하여 다음 단계의 작업을 진행한다
#그레이 스케일 및 이진화
gray1 = cv2.cvtColor(rotated_image, cv2.COLOR_BGR2GRAY)
_, binary1 = cv2.threshold(gray1, 127, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU )

# 회전한 이미지의 컨투어 찾기
contours1, _ = cv2.findContours(binary1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 회전한 이미지의 가장 큰 컨투어 찾기
largest_contour1 = max(contours1, key=cv2.contourArea)

# 새로운 이미지 생성 (검은색 배경)
new_image1 = np.zeros_like(binary1)

# 회전한 이미지의 가장 큰 컨투어 중에서 면적이 가장 큰 폐곡선 찾기
largest_closed_contour1 = max([c for c in contours1 if cv2.contourArea(c) > 0], key=cv2.contourArea)

# 면적이 가장 큰 폐곡선 안에 있는 흰색 점들만 남기고 나머지는 삭제하여 새 이미지에 저장
cv2.drawContours(new_image1, [largest_closed_contour1], -1, (255), thickness=cv2.FILLED)

# 회전한 이미지의 컨투어를 포함하는 가장 작은 사각형을 찾는다
min_rect1 = cv2.minAreaRect(largest_closed_contour1)

# minAreaRect에서 반환한 4개 점은 실수값을 갖으므로, 사용하려면 정수로 변환한다
# Convert it to box points (four points)
box_points1 = cv2.boxPoints(min_rect1)
box_points1 = np.intp(box_points1)

# 4개 점을 좌표값에 따라서 번호를 부여한다
# 원래의 의도는 좌상, 우상, 좌하, 우하 순서로 P1, P2, P3, P4를 부여하려고 하였다
# 그러나 프로그래머의 일반적인 코드 규칙에 따라서 점의 번호를 부여하기로 생각을 바꿨다.
# The order will be P1 (top-left), P2 (top-right), P3 (bottom-left), P4 (bottom-right)
box_points1 = sorted(box_points1, key=lambda x: (x[1], x[0]))
if box_points1[0][0] > box_points1[1][0]:
box_points1[0], box_points1[1] = box_points1[1], box_points1[0]
if box_points1[2][0] > box_points1[3][0]:
box_points1[2], box_points1[3] = box_points1[3], box_points1[2]

# 프로그래머의 일반적인 코드 부여 방법에 따라서 점의 번호를 정했다
# 점의 번호를 앞의 점과 다르게 해서 혼동을 피했다
P11 = box_points1[0]
P22 = box_points1[1]
P33 = box_points1[2]
P44 = box_points1[3]
# 4개 점의 좌표를 이용하여 사각형 영역을 택하여 새 그림 파일로 저장한다
k = rotated_image[P11[1]:P33[1], P11[0]:P22[0]]

cv2.imwrite("C:\\output\\{}".format(image_name), k)


sys.exit()



추천 비추천

1

고정닉 1

0

댓글 영역

전체 댓글 0
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 끝까지 다 본 걸 후회하게 만든 용두사미 드라마는? 운영자 25/07/07 - -
AD 디지털 액세서리 기간한정 세일! 운영자 25/07/11 - -
2870840 좌파의 특권의식과 이중성 ♥냥덩이♥갤로그로 이동합니다. 07.10 20 0
2870839 한국 환경이랑 해외환경 차이는 카톡이랑 텔레그램만봐도 앎. ㅆㅇㅆ(124.216) 07.10 34 0
2870838 현업 7년차인데 코딩테스트 개조졌음 [5] 프갤러(211.218) 07.10 181 0
2870837 집에가자 개멍청한유라갤로그로 이동합니다. 07.10 39 0
2870836 텔레그램 봇 지원해주는게 참 좋긴함. 왜 카톡은 그렇게 안할까 [1] ㅆㅇㅆ(124.216) 07.10 35 0
2870835 텔레그램 얘기 나와서 하는 말인데 카톡 솔직히 병신임 [1] 프갤러(218.154) 07.10 44 0
2870834 텔레그램이 왜 유명한거임 [3] ㅇㅇ(164.125) 07.10 51 0
2870833 누가 멍유 스토킹 좀 막아주면 나님 ㄹㅇ 탈갤함 [2] ♥냥덩이♥갤로그로 이동합니다. 07.10 45 0
2870832 하이닉스 평단 295,000원에 들어감 ㅜㅠ [1] ㅇㅇ(39.7) 07.10 45 0
2870831 ■컴공과에서 개발자, 전산말고 다른 진로는 없나요 [2] ㅇㅇ갤로그로 이동합니다. 07.10 71 0
2870829 어깨 아프다 [4] 루도그담당(211.235) 07.10 40 0
2870828 연봉인상 15%면 많이 오른거냐 [3] 프갤러(220.87) 07.10 82 0
2870827 군대에서 이거 진짜 된적 있나요? [8] 프갤러(106.101) 07.10 65 0
2870826 내 몸에서 한남냄새가나요 [10] 개멍청한유라갤로그로 이동합니다. 07.10 80 0
2870825 카카오 코테 질문 [2] 프갤러(219.255) 07.10 151 0
2870824 기술토론 하는건 좋은데 과도하면 비호감임 [1] 프갤러(106.101) 07.10 59 0
2870823 냥덩이가 웅장해진당.. ♥냥덩이♥갤로그로 이동합니다. 07.10 26 0
2870822 인생 참 부질 없어 [1] 프갤러(59.26) 07.10 34 0
2870821 140 ♥냥덩이♥갤로그로 이동합니다. 07.10 33 0
2870820 체력은 정직하당 By 나님 ♥냥덩이♥갤로그로 이동합니다. 07.10 25 0
2870819 나님 보물창고 발겨어언!!!!!!!!! [1] ♥냥덩이♥갤로그로 이동합니다. 07.10 38 0
2870818 불법 프로그램 사용하는 학원 이거 뭐임 [1] 프갤러(218.148) 07.10 67 1
2870817 뿡야하구푼데 자꾸 끙야 나오려행.. [2] ♥냥덩이♥갤로그로 이동합니다. 07.10 44 0
2870816 어떤 새끼가 ai 10배 생산성 물타기 했는진 모르겠는데 [6] 프갤러(218.154) 07.10 88 1
2870815 크래프톤 정글 게임랩 4기 / 게임테크랩 2기 (~7.18) [1] 프갤러(175.223) 07.10 163 0
2870814 파이썬 쓸꺼면 pylance 사용해서 써야함 ㅆㅇㅆ(124.216) 07.10 53 0
2870813 파이썬 좀 짜증난다. [2] 프갤러(218.154) 07.10 65 0
2870812 게임쪽이랑 서버쪽 밴엔드가 많이 다르긴해 [2] ㅆㅇㅆ(124.216) 07.10 64 0
2870810 더럽고 치사해서 때려치기 전에 해봐야할 것 프갤러(218.154) 07.10 37 0
2870809 게임회사 개발자 출신들은 별로 잘 인정 안해줌? [1] 프갤러(110.13) 07.10 79 0
2870808 자기가 말한거 다 되는데 자기가 깜빡해서 말 안한걸 [8] ㅆㅇㅆ(124.216) 07.10 64 0
2870807 chatgpt 이새끼 진짜 존나 빡대가리네 프갤러(61.72) 07.10 52 0
2870806 스윗 40 50 야옹아재는 못하는거 프갤러(211.235) 07.10 34 0
2870805 115 ♥냥덩이♥갤로그로 이동합니다. 07.10 22 0
2870804 잼각하 25마넌 감사합니다 꾸벅~~~ 프갤러(112.144) 07.10 31 1
2870803 하드웨어 속도체감 [2] ♥냥덩이♥갤로그로 이동합니다. 07.10 58 0
2870802 [대한민국] 많은 사람들이 트럼프를 지지하는 이유 프갤러(121.172) 07.10 35 0
2870800 정좌불능증 재현갤로그로 이동합니다. 07.10 22 0
2870799 자바 책 추천좀 프갤러(211.54) 07.10 16 0
2870797 자료구조 책은 머 봐야됨? [2] 프갤러(49.167) 07.10 80 0
2870796 나님 기분 ㄱㅆㅅㅌㅊ !! ♥냥덩이♥갤로그로 이동합니다. 07.10 30 0
2870795 윅스같이 홈피만드는 서비스들 ai 땜에 ㅇㅇ(118.235) 07.10 39 0
2870794 Sm은 프로그램 다 파악해노니 ㅇㅇ(211.235) 07.10 38 0
2870792 드럽고 치사해서 때려칠까? [1] 프갤러(59.16) 07.10 49 1
2870791 짱깨폭염 ㅅㅂ 짱깨들이 더 날씨좋누 뒷통수한방(1.213) 07.10 24 0
2870790 나 누구랑 키배떳는데 ㅇㅇ갤로그로 이동합니다. 07.10 35 0
2870789 "1691명 유혹해 성관계·불법 촬영"…여장남자에 발칵 발명도둑잡기(211.246) 07.10 37 0
2870788 나님 목표 ㅆㅅㅌㅊ !! ♥냥덩이♥갤로그로 이동합니다. 07.10 49 0
2870787 내 시급이 이런 식으로 정해진다니... 황당하실 겁니다 발명도둑잡기(211.246) 07.10 37 0
2870786 尹 재수감되는 3.7평 독방 발명도둑잡기(211.246) 07.10 48 0
뉴스 ‘슈퍼 루키’ 조째즈, 오늘(11일) 신곡 ‘한잔의 노래’ 발매! 디시트렌드 07.11
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2