디시인사이드 갤러리

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

갤러리 본문 영역

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

몬발켜갤로그로 이동합니다. 2024.04.30 12:37:03
조회 61 추천 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
등록순정렬 기준선택
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 연예인 안됐으면 어쩔 뻔, 누가 봐도 천상 연예인은? 운영자 24/06/17 - -
공지 프로그래밍 갤러리 이용 안내 [71] 운영자 20.09.28 35688 62
2714992 1페이지하나에 정신병자가 0.3333명은되는듯 ㅇㅇ(14.33) 02:40 7 0
2714989 백종원씨 마지막날이라 반찬에 다시다 넣어서 팔아버린다. 헬마스터갤로그로 이동합니다. 02:20 13 0
2714987 개발자형님들 궁금한게잇삼 [2] ㅇㅇ갤로그로 이동합니다. 02:14 26 0
2714986 박스 줍는 노인 입갤이요 ㅇㅅㅇ ㅇㅅㅇ(106.102) 02:09 11 0
2714982 사업의 성공은 개발이 전부가 아니다 [3] 헬마스터갤로그로 이동합니다. 01:53 29 0
2714979 순수하게 개발만 한다고 하면 우분투도 한번은 써봄직할듯 [3] 프갤러(14.39) 01:42 26 0
2714978 아 오늘도 늦게출근하겠노 프갤러(39.117) 01:19 21 0
2714977 프론트도 하는일 있지않나? [4] ㅇㅇ(223.38) 01:15 61 0
2714976 리눅스 왜씀? [14] 프갤러(49.165) 01:12 80 0
2714975 프론트 <- 이 시발새끼들은 하는게 없음 [8] 프갤러(14.34) 01:05 79 0
2714974 개발자들 대부분 앓고있는 질환이있는듯 [2] 프갤러(112.165) 01:02 73 0
2714973 웹 개발자 vs 윈도우어플리케이션 응용개발자 프갤러(59.18) 01:01 26 0
2714971 프론트 잘하는 방법 깨달았다 반박시 프알못 ㄹㅇ [16] ㅇㅇ갤로그로 이동합니다. 00:46 89 0
2714970 내일부터 다시 정신과를 다녀볼까 합니다. 약받아 먹으려구요 [2] ㅇㅇ(123.213) 00:46 41 0
2714969 개발자는 꼼꼼한 사람이 잘한다 [3] 프갤러(39.117) 00:45 54 0
2714968 누가 더 창의적임? [1] 프갤러(183.101) 00:40 29 0
2714967 미국에서 사망한 넥슨 김정주 회장 발명도둑잡기갤로그로 이동합니다. 00:38 23 0
2714965 중국 게임 루트킷 발명도둑잡기갤로그로 이동합니다. 00:32 12 0
2714964 난 좀 취업 루트 어중간하게 탄 듯 [6] ㅇㅇ(39.117) 00:32 73 0
2714963 마지막 쾌락의 밤입니다... 전역하면 이렇게 살 순 있을까요?? [2] ㅇㅇ(123.213) 00:31 42 0
2714962 음기 충전 발명도둑잡기갤로그로 이동합니다. 00:28 18 0
2714961 병신새끼들 다 자러갔나보네 프갤러(112.165) 00:27 19 0
2714960 데비안/우분투 LTS는 뭐가 문제인가. [40] ☆단비☆갤로그로 이동합니다. 00:27 61 1
2714958 우분투 스냅은 빅브라더 기술입니다 [6] 발명도둑잡기갤로그로 이동합니다. 00:26 31 0
2714956 appimage 가 좋긴한데... ☆단비☆갤로그로 이동합니다. 00:18 17 0
2714955 자바 스위치문 ㅈㄴ 섹시한데 [1] 타입스크립트갤로그로 이동합니다. 00:14 40 0
2714954 비전공까는새끼들아 [12] 프갤러(112.165) 00:12 133 0
2714952 멜버른에서 7년 일한 현직이 한국와서 느낀점 [1] ㅇㅇ(1.239) 00:11 51 0
2714951 언어 최신버전 안쓰는건 왜 그런거임? [2] 프갤러(14.34) 00:08 43 0
2714950 가난이 밉다... 치킨먹을돈이 없는 인생이 그저 밉다... [9] ㅇㅇ(123.213) 00:05 41 0
2714949 애들아 전략과 재능으로 패배는 없어! [3] 40대프린이(220.87) 06.19 46 2
2714948 인생 두배로 쉽게 사는법 알려줌 [1] ㅇㅇㅇㅇ(121.154) 06.19 65 2
2714947 pc유지보수 이딴건 뒤져도 하지마셈 [3] 프갤러(220.88) 06.19 67 0
2714946 전역할때 깔깔이랑 디지털티 이런거 가지고나옴?? ㅇㅇ(123.213) 06.19 17 0
2714944 오늘 나님은 토런트 다운받을 때 법에 저촉되지 않는 방법을 발견 [3] ☆단비☆갤로그로 이동합니다. 06.19 47 1
2714943 서성한 상경주전 컴공복전 싸피들어갔는데 [5] 프갤러(175.124) 06.19 72 1
2714942 it 유지보수는 별로임? [34] 프갤러(121.170) 06.19 146 0
2714941 42서울 경산 가본사람 있음? [7] ㅇㅇ(1.251) 06.19 82 0
2714940 “여직원 성폭행한 권익위 간부 영장기각 이해안돼”… 검찰시민위가 ... 뉸턴(211.170) 06.19 13 0
2714939 사수가 안알려주는 이유가 있음 [3] 프갤러(61.75) 06.19 81 1
2714938 신입 개발자 오늘 한 일.list [4] cvs.갤로그로 이동합니다. 06.19 101 0
2714937 88올림픽 요트 국대로 나가려했던 노무현과 보물섬으로의 항해 [2] 발명도둑잡기갤로그로 이동합니다. 06.19 23 0
2714936 코로나 이전 이후 따지는 새끼들특 ㅇㅇ(106.102) 06.19 32 0
2714935 우분투는 왜 flatpak을 놔두고 snap을 쓰는가 [8] 박민준갤로그로 이동합니다. 06.19 42 0
2714934 국비에는 찐따와 일찐이 공존함 [2] ㅇㅇ(39.7) 06.19 70 0
2714933 오 마이 컴퓨터의 위엄 ☆단비☆갤로그로 이동합니다. 06.19 41 0
2714932 원래 API 문서 작성할때 curl 명령어 적어야함? [2] ㅇㅇ(121.173) 06.19 36 0
2714931 아씨발 아마존 [2] 키비갤로그로 이동합니다. 06.19 40 0
2714930 서울 영등포경찰서는 지난 12일 서울남부지검에 담당 검사에 대한 직무 배 뉸턴(211.170) 06.19 22 0
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2