디시인사이드 갤러리

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

갤러리 본문 영역

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

몬발켜갤로그로 이동합니다. 2024.04.30 12:37:03
조회 56 추천 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/05/20 - -
2698614 임베디드 게임 금융 다 멸망했는데 웹땔깜만이 미래냐? [5] 공기역학갤로그로 이동합니다. 05.21 108 0
2698613 저희 템장님 이름은 응우엔 입니다ㅇㅅㅇㅋㅋㅋ [1] AppHiki갤로그로 이동합니다. 05.21 58 0
2698612 덱스 무섭게 생겻다고 생각하는거 나뿐이냐? 프갤러(59.14) 05.21 35 0
2698610 신입 질문. 몇백대일로 취업하면 연봉 회사내규 무조건 간다? 프갤러(59.16) 05.21 59 0
2698609 + 네이버메일 vs 지메일 qu(121.171) 05.21 18 0
2698608 청년 개발자는 취업난에 아우성인데 정부 베트남 인도 개발자 수입함 [2] 초코냥갤로그로 이동합니다. 05.21 121 0
2698607 지피티 이거 뭐냐 프갤러(118.235) 05.21 26 0
2698606 안되는게 되면 딸치기만큼 재밋단말이지 [2] 헬마스터갤로그로 이동합니다. 05.21 32 0
2698605 베트남 개발자와 일해봤다 [6] 유동갤로그로 이동합니다. 05.21 117 1
2698603 국비하면서 학벌 중요성 깨달음 ㅋㅋㅋㅋㅋㅋㅋㅋ [2] 프갤러(223.39) 05.21 163 1
2698602 해외로 갈 수 있는 길 좀 열어놔야 되는 거 아님? [1] 프갤러(121.172) 05.21 46 0
2698601 학부 2년차 평균이 인공지능보다 코드를 잘짜나?(x) ㅇㅇ(121.186) 05.21 48 0
2698600 학식충인데 교수 개패고 싶어 [4] 프갤러(210.101) 05.21 47 0
2698599 배트남 개발자가 좆소 중급개발자보다 몸값높다 ㅇㅇ(118.33) 05.21 46 0
2698598 베트남 개발자 - 프갤러(121.172) 05.21 34 0
2698596 베트남 개발자 온다 천재(220.77) 05.21 44 0
2698595 어차피 대한민국은 점점 공채로 취업하기 어려워짐 ㅇㅅㅇ [1] ㅇㅇ(121.186) 05.21 76 0
2698593 포지션 제안 왔는데 프갤러(121.172) 05.21 44 1
2698591 넛지헬스 저기는 무슨 병특을 1년 내내뽑나 프갤러(59.16) 05.21 43 0
2698590 하아품 프갤러(121.172) 05.21 15 0
2698589 난 외로움을 벗삼는 고고한 개인이라 개따위 키우지 않지만 ㅇㅅㅇ [1] ㅇㅇ(121.186) 05.21 23 0
2698588 요즘 자주 보이던 길냥이들이 안보여.. 캣맘들이 잡아갔나? ♥순수퓨어냥덩♥갤로그로 이동합니다. 05.21 24 0
2698587 내 게임이 그래픽이 솔직히 구리긴한데 [1] ㅇㅇ(39.120) 05.21 49 1
2698586 그래픽이 별로여도 게임에 돈을 질러줄까? [6] ㅇㅇ(39.120) 05.21 50 0
2698585 운동하러가야지 이더리움(39.125) 05.21 17 0
2698584 인공눈물 어디다 놨는지 보이질 않네 ㅇㅇ(180.233) 05.21 16 0
2698583 허언증 ㅂㅅ들 [1] 프갤러(118.235) 05.21 43 0
2698581 근데 개 옷입히는게 한국만의 문화냐?? [2] 40대프린이(121.161) 05.21 45 0
2698580 지금 신입 백엔드 4천이상 취준 괜찮은곳 스펙 알려준다 [2] ㅇㅇ(175.223) 05.21 191 1
2698579 사업을 하려면 뭐든지 가치를 생각해야함 ㅇㅇ(39.120) 05.21 29 0
2698577 서울대 동문 12명을 비롯한 여성 61명의 사진을 합성한 음란물을 만들어 프갤러(121.134) 05.21 86 0
2698576 IT 회사들 개발 신입한테 요구하는 기준 ㅈㄴ높네 [2] 프갤러(112.150) 05.21 145 0
2698575 윈도우11은 졸작인데 12는 제대로 만들어서 나오겠지? 프갤러(14.39) 05.21 25 0
2698571 개발자도 적성 ㅈㄴ타지 [2] 클갤(118.235) 05.21 102 0
2698570 에바 주제의식은 이데온에서 빌려온거임 프갤러(121.186) 05.21 21 0
2698569 지금 국비진입자들 마인드가 저거구나 ㅇㅇ(223.62) 05.21 94 0
2698568 기분이 좋을땐 냥덩이 흔들어봥❤+ ♥순수퓨어냥덩♥갤로그로 이동합니다. 05.21 17 0
2698567 신입 취직문제는 교육기관과 틀딱들 문제가 제일 큼 ㅇㅇ(218.157) 05.21 51 0
2698566 성공한 사람들 특징이 새벽에도 일함 [2] 프갤러(14.39) 05.21 64 0
2698564 일본인들 우크라이나 그닥 안좋아하더군요 [3] 프로외노자갤로그로 이동합니다. 05.21 77 0
2698563 잘 몰라서 물어보는데 개발자 40되면 나가리임? [5] ㅇㅇ(106.101) 05.21 99 0
2698562 신입 안뽑는건 너무 한듯 프갤러(172.225) 05.21 55 0
2698560 틀딱들이 스프링 좋아하는이유 [2] ㅇㅇ(218.157) 05.21 85 0
2698559 적성에 안 맞으면 일찌감치 포기해라 ㅇㅇ(114.30) 05.21 42 0
2698558 나님은 스타2 존나 재밌어 ㅇㅅㅇㅋ 나트륨찡갤로그로 이동합니다. 05.21 21 0
2698557 개발자 그만둘까.. [12] 프갤러(106.101) 05.21 208 1
2698556 진로 고민 [1] 프갤러(223.33) 05.21 24 0
2698555 나님 시작합니당❤+ ♥순수퓨어냥덩♥갤로그로 이동합니다. 05.21 25 0
2698554 gpt 쓰는걸 안좋게 보는 이유가뭐임 ? [6] 프갤러(1.224) 05.21 113 3
2698553 클리너 아이디이거 뭐로하면 됨? 프갤러(121.163) 05.21 22 0
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2