디시인사이드 갤러리

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

갤러리 본문 영역

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

몬발켜갤로그로 이동합니다. 2024.04.30 12:37:03
조회 59 추천 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/03 - -
공지 프로그래밍 갤러리 이용 안내 [71] 운영자 20.09.28 35328 62
2708797 it 일은 많은데 다 박봉 ㅇㅇ갤로그로 이동합니다. 05:36 12 0
2708796 출근완료 보법E노무현갤로그로 이동합니다. 05:34 5 0
2708795 조코딩 실력 어느정도임 [2] 프갤러(175.200) 05:10 38 0
2708794 종부세를 덜 내는 최선의 방법은 전국적 집값 폭락이다 발명도둑잡기갤로그로 이동합니다. 04:59 8 0
2708793 오늘의 발명 실마리: 국세청이 세금 걷는 시뮬레이숀 게임 발명도둑잡기갤로그로 이동합니다. 04:46 11 0
2708792 "종부세 25억 말이 되나"…'폭탄' 맞은 골프장 '초비상' 발명도둑잡기갤로그로 이동합니다. 04:17 11 0
2708791 20대 청년 동지들은 5만원만 꿔달라고 하는데 발명도둑잡기갤로그로 이동합니다. 04:11 15 0
2708790 음기 충전 발명도둑잡기갤로그로 이동합니다. 04:03 21 0
2708789 방금 인스타그램 추천 발명도둑잡기갤로그로 이동합니다. 04:00 22 0
2708788 미래의 어느 역사학자들의 대화라는데 (요약편) 프갤러(211.241) 03:58 12 0
2708787 우리차에는.. ㅇㅅㅇ 헤르 미온느갤로그로 이동합니다. 03:56 10 0
2708785 미래의 어느 역사학자들의 대화라는데 프갤러(211.241) 03:52 13 0
2708784 박스 줍는 노인 입갤이요~ ㅇㅅㅇ 헤르 미온느갤로그로 이동합니다. 03:49 11 0
2708774 맥도날드 햄버거 대학교 발명도둑잡기갤로그로 이동합니다. 02:51 14 0
2708773 국가별 행복도 [2] 발명도둑잡기갤로그로 이동합니다. 02:44 26 0
2708770 국가별 평균 지능 발명도둑잡기갤로그로 이동합니다. 02:39 17 0
2708768 촛불혁명을 갈취해 대동령이 된 후 죄인 박근혜를 사면 발명도둑잡기갤로그로 이동합니다. 02:24 15 0
2708767 아니 ㄹㅇ이었네 ㅅㅂ 당연히 드립인줄 알았는데 프갤러(223.38) 02:20 56 2
2708766 원종이는 교도소생활은 할만할까? [3] 헬마스터갤로그로 이동합니다. 02:10 62 1
2708765 나는 자바가 싫어요 ㅇㅇ갤로그로 이동합니다. 02:07 33 0
2708764 여기가 원종이 탄생갤인가요? [5] ㅇㅇ(106.101) 02:01 119 9
2708763 국비 개발자 취업 실패해서 틀려고 하는데 현실적인 조언 부탁드립니다 [10] 프갤(118.44) 01:54 133 2
2708762 코리아나-손에 손 잡고, 달러의 벽을 넘어서 발명도둑잡기갤로그로 이동합니다. 01:50 18 0
2708761 성재기씨가 투신전에 자살한다고 말했었더라 [2] 헬마스터갤로그로 이동합니다. 01:43 67 0
2708760 님들 에디터 화면 어두움? 밝음? ㅇㅅㅇ? 프갤러(71.204) 01:42 25 0
2708758 예의상 하는 연락이랑 진짜연락이랑 어케구분함? [1] ㅇㅇ(203.248) 01:40 32 0
2708755 나 프란시스 딱국이야 히힛 [2] 딱국갤로그로 이동합니다. 01:14 28 0
2708754 장고에서 탬플릿 html에 script못쓰나요? 프갤러(223.38) 01:12 21 0
2708752 오늘 어쩐지 학교에 사람이 없다했더니 [5] linux갤로그로 이동합니다. 01:02 63 0
2708749 상상도 못한 오렌지색의 정체 [1] 발명도둑잡기갤로그로 이동합니다. 00:55 22 0
2708748 내일도 출근하는 사람 없지? [7] cvs.갤로그로 이동합니다. 00:53 52 0
2708746 명문대(sky서성한) 애들도 프론트 백엔드 개발자함??? [1] 딘퐁갤로그로 이동합니다. 00:49 94 0
2708743 취준생 없는 프갤 있었으면 좋겠다 [3] 프갤러(61.74) 00:43 66 0
2708742 이번주도 다들 고생했어요 [4] 멍청한유라ㅋ갤로그로 이동합니다. 00:43 45 0
2708741 컴공 3학년인데, 관심 분야가 뭔지 잘 모르겠습니다. [17] 프갤러(121.131) 00:41 110 0
2708740 주한미군 부대 위에 표현의 자유 풍선을 날려라 [1] 발명도둑잡기갤로그로 이동합니다. 00:35 14 0
2708739 뭐여 비공개 릴레이 키니까 아스카영원히사랑해갤로그로 이동합니다. 00:34 28 0
2708738 주방에서 [2] 발명도둑잡기갤로그로 이동합니다. 00:32 18 0
2708737 오늘의 미술 기획 실마리: 거대한 스폰지 주먹이 사람을 누름 [1] 발명도둑잡기갤로그로 이동합니다. 00:28 16 0
2708736 취업 너무안된다 진짜루~~~ [10] ㅇㅇ갤로그로 이동합니다. 00:16 144 1
2708735 프갤러 어렸을 때 [1] 발명도둑잡기갤로그로 이동합니다. 00:10 55 0
2708734 인공지능 결제하려는데 머가 좋도 많노 프갤러(125.130) 00:07 27 0
2708733 갑자기 괜찮은 생각이 남 ㅇㅅㅇ ㅇㅇ(121.186) 00:04 21 0
2708732 종이로 리모콘 흉내 발명도둑잡기갤로그로 이동합니다. 00:01 13 0
2708731 웹 개발자 전망 혹시 [5] 프갤러(118.39) 00:00 116 0
2708730 뻥튀기 옛날엔 다들 버텼다 [1] ㅇㅇ(117.111) 06.06 43 0
2708729 뻥튀기 장점 [1] 프갤러(220.88) 06.06 38 0
2708728 vdi 쓰는 회사 치고 정상이 없음 [6] ㅇㅇ(117.111) 06.06 40 0
2708727 형들 데이터를 명령어만으로 입출력을 가능하게 해주는게 뭐야? [1] ㅇㅇ(180.80) 06.06 25 0
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2