디시인사이드 갤러리

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

갤러리 본문 영역

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

몬발켜갤로그로 이동합니다. 2024.04.30 12:37:03
조회 73 추천 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 - -
2870507 가끔 뭔 공산주의 같은 마인드를 한놈들이 보여. 노동의 가치창출 말이야 [1] ㅆㅇㅆ(124.216) 07.08 64 0
2870506 [스트레이트] "검찰 역사 최악의 치욕" 발명도둑잡기(118.216) 07.08 136 0
2870505 "'팔레스타인 집단 학살' 가담해 한국기업 이익 창출했다" 발명도둑잡기(118.216) 07.08 32 0
2870504 gpt는 답 아니면서 답인 것처럼 말하는 거 많은데 [9] 아스카영원히사랑해갤로그로 이동합니다. 07.08 114 0
2870503 개발자는 자기의지 가지고 성장 안됨 [2] 프갤러(1.245) 07.08 110 0
2870502 취직을 했는데 안간거지 취직을 못한게 아닌데 이 차이 구분을 못하노 ㅆㅇㅆ(124.216) 07.08 59 0
2870501 “어? 예쁜 조개다” 덥석 잡았다가 죽을 뻔했습니다…정체 알고 보니 발명도둑잡기(118.216) 07.08 55 0
2870500 곽원태 천안시 서북구청장, 중국 여행 중 갑작스러운 별세 발명도둑잡기(118.216) 07.08 65 0
2870497 게임업계의 창과 방패 (크랙방지 vs 크래커) [1] 발명도둑잡기(118.216) 07.08 49 0
2870496 커서 살까말까 고민되네 [3] 프갤러(211.46) 07.07 102 0
2870495 고춧가루 ㅇㅇ(117.111) 07.07 34 0
2870494 갠적으로 코딩 실력보다 단체에서는 조직 요구사항을 빠르게 [2] ㅆㅇㅆ(124.216) 07.07 100 1
2870493 개발 고수, 중수, 초보 [2] ㅇㅇ(125.179) 07.07 115 0
2870492 프갤 오는 시니어들은 전부 자기는 잘하는데 승진하는 애들은 ㅆㅇㅆ(124.216) 07.07 54 0
2870491 신입에게 조언. 배워야 공부해야 할 것. 퇴사 사유. [4] 프갤러(59.16) 07.07 168 0
2870490 서유리 님 께서 사회인 코스프레 하지말라고 발언을 말하셨는데, 넥도리아(121.139) 07.07 93 0
2870489 깃도 공부할 거 많네 [6] 아스카영원히사랑해갤로그로 이동합니다. 07.07 139 0
2870487 잼민이 성능 미쳣네 ㄹㅇ 프갤러(61.75) 07.07 58 0
2870485 자동화 관련 질문 (http호출) [2] ㅇㅇ(114.206) 07.07 63 0
2870484 디시에 악플유저들은 새싹 원종이임 조루디(118.235) 07.07 60 0
2870483 맥미니 m4 32 512 개발하기 충분? [2] 조루디(118.235) 07.07 72 0
2870482 알고리즘 자료구조 이런거 누가 만들었냐 [1] 뒷통수한방(1.213) 07.07 71 0
2870480 Blockudoku 알고리즘 대결 만들었어 한번만해죠 프갤러(118.235) 07.07 50 0
2870479 자사 서비스 있는 스타트업 어떰? 프갤러(1.233) 07.07 42 0
2870477 재야학계 책보고 아저씨, 제가 역사는 모르지만 [1] 넥도리아(175.196) 07.07 40 0
2870474 근데 슼유동아 궁금한게 한 8개월 넘게 따라다녔는데 안 지겹냐 [3] ㅆㅇㅆ(124.216) 07.07 68 0
2870472 현실부정하다 아카이브 보여주면 빤스런 하는건 똑같노 ㅇㅇ(211.235) 07.07 72 5
2870470 또또 아카이브 내 글 따가며 도배하는 모습이 똑같노 ㅋㅋㅋ ㅆㅇㅆ(124.216) 07.07 56 0
2870469 아니 근데 신기하지 않냐 저 슼유동 VPN까지 써가며 날 증오하는데 [1] ㅆㅇㅆ(124.216) 07.07 41 0
2870467 프갤에서 념글구걸하고 개추주작하고 [5] ㅇㅇ(211.235) 07.07 75 4
2870466 류도그담당=114.202=59.14=ㅆㅇㅆ [1] ㅇㅇ(45.84) 07.07 85 5
2870464 슼 유동 점마 대단한게 49.165행님한테도 개좆털리고 [3] ㅆㅇㅆ(124.216) 07.07 59 0
2870462 준석이 프로그램 비평하셈 [1] ㅇㅇ(211.241) 07.07 103 0
2870460 [그래픽] 여름휴가 언제 많이 가나 발명도둑잡기(118.216) 07.07 44 0
2870458 또 조현병 슼유동 와서 시비거노 [2] ㅆㅇㅆ(124.216) 07.07 52 0
2870456 정치글, 남탓 무한반복 [1] ㅇㅇ(211.235) 07.07 60 4
2870455 코딩 잘하려면 이렇게만 하세요 프갤러(175.115) 07.07 61 0
2870452 일본하면 카타나 수리검 닌자 사무라이 [4] 배구공(119.202) 07.07 58 0
2870450 ㅅㅂ ㅈ됨 [4] ㅇㅇ(180.65) 07.07 104 0
2870449 근데 재매이햄 대통령으로써 능력있게 나름 잘하고 계시노 [6] ㅆㅇㅆ(124.216) 07.07 100 2
2870448 ADHD용 플래너 앱 기획했는데 어떰? ㅇㅇ(118.235) 07.07 53 0
2870447 일본이라고 부르는 것부터가 문제다. 프갤러(223.55) 07.07 55 0
2870446 민생 소비 쿠폰 뭐 사야하나. 데이터 복구하고싶은데 그러면 안될 것 같해 넥도리아(175.196) 07.07 33 0
2870444 짱깨폭염 이시발 뒷통수한방(1.213) 07.07 33 0
2870443 나이가 들수록 아는 것에 대해서 자신이 없어지지 않냐? [1] ㅆㅇㅆ(124.216) 07.07 75 0
2870442 나이가 들수록 점점 아는게 적어지고 화내는 기력조차 없어짐 ㅆㅇㅆ(124.216) 07.07 63 0
2870441 [경축]아스카 주식계좌 2000만원 돌파 [4] 아스카영원히사랑해갤로그로 이동합니다. 07.07 108 2
2870440 우왁굳씨도 논란 후 휴가간다는구나 [3] 헬마스터갤로그로 이동합니다. 07.07 79 0
2870439 AI 자동화는 시장이 될수있을까 프갤러(124.54) 07.07 37 0
2870438 컴퓨터 이름이 레이드 구축할 때마다 바뀌어요. 넥도리아(175.196) 07.07 41 0
뉴스 밀레나, 오늘(11일) 첫 정규앨범 'Where to Begin' 발매! 전곡 작사·프로듀싱 참여 디시트렌드 07.11
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2