728x90
반응형
728x90
반응형

 

 

 

 

 

 

 

import sys
from distutils.dir_util import copy_tree
from PyQt5.QtCore import QProcess, Qt
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import *
from PyQt5 import uic
from PyQt5.QtWidgets import QApplication, QMainWindow
import numpy as np
import cv2
import tensorflow as tf

form_class = uic.loadUiType("cnn_pj.ui")[0]

class WindowClass(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

#   ----------------------------↓↓↓변수↓↓↓-----------------------------------

        # 모델
        self.model_path = ""

        # 데이터셋 파일 저장 리스트
        self.dataset_list_dir = ""

        # 데이터셋 적용폴더 저장 리스트
        self.dataset_dir = ""

        # 결과폴더 절대경로
        self.result_dir = ""

        # 텍스트 데이터 모든파일의 절대경로
        self.text_all_list = []

        # 그림 데이터 모든파일의 절대경로
        self.img_all_list = []

        # 화면에 표시된 데이터셋 파일과 결과파일의 절대값 주소
        self.original_img = ""
        self.result_img_img = ""

        # treeView 목록 파일을 클릭하면 그 파일의 절대값을 저장
        self.tree_View_file_click = ""

        # 마진조절
        self.margin = 15

        # area조절
        self.area = 1000

#   ----------------------------↑↑↑변수↑↑↑-----------------------------------

#   ----------------------------↓↓↓버튼↓↓↓-----------------------------------

        # 모델/데이터셋 불러오기 버튼
        self.pushButton_2.clicked.connect(self.datasetDirSelect)
        # 결과폴더 선택버튼
        self.pushButton_7.clicked.connect(self.resultDir)
        # 리셋버튼
        self.pushButton_5.clicked.connect(self.reset)
        # 마진조정버튼
        self.pushButton_margin.clicked.connect(self.marginC)
        # area조정버튼
        self.pushButton_area.clicked.connect(self.areaC)
        # 결과확인 버튼 test
        self.pushButton_result.clicked.connect(self.numberDetection)

#   ----------------------------↑↑↑버튼↑↑↑-----------------------------------

#   ----------------------------↓↓↓함수들↓↓↓--- --------------------------------

    # 모델위치 선택 함수
    def modelSelect(self):
        file_path = QFileDialog.getOpenFileName(self, 'Attach File')[0]
        self.model_path = file_path

    # 데이터셋이 들어있는 폴더를 선택하는 함수
    def datasetDirSelect(self):
        file_path = QFileDialog.getExistingDirectory(self, "select Directory")
        self.dataset_list_dir = file_path
        self.model_file_system = QFileSystemModel()
        self.model_file_system.setRootPath(file_path)
        self.model_file_system.setReadOnly(False)
        self.treeView.setModel(self.model_file_system)
        self.treeView.setRootIndex(self.model_file_system.index(file_path))
        self.treeView.doubleClicked.connect(lambda index: self.treeViewDoubleClicked1(index))
        self.treeView.setDragEnabled(True)
        self.treeView.setColumnWidth(0, 300)

    # treeView 더블클릭 시 절대값 추출함수
    def treeViewDoubleClicked1(self, index):
        self.tree_View_file_click = self.model_file_system.filePath(index)
        self.original_img = self.tree_View_file_click
        pixmap = QPixmap(self.tree_View_file_click)
        pixmap = pixmap.scaled(self.label.size(), aspectRatioMode=True)
        self.label.setPixmap(pixmap)

    def treeViewDoubleClicked2(self, index):
        self.tree_View_file_click = self.model_file_system.filePath(index)
        self.result_img = self.tree_View_file_click
        pixmap = QPixmap(self.tree_View_file_click)
        pixmap = pixmap.scaled(self.label_2.size(), aspectRatioMode=True)
        self.label_2.setPixmap(pixmap)

    # 실행버튼 함수
    def runFile(self):
        copy_tree(self.dataset_list_dir, self.dataset_dir)
        file_path = self.model_path
        process = QProcess(self)
        process.start('python', [file_path])

    # 데이터셋을 적용할 폴더 선택 함수
    def datasetDir(self):
        directory_path = QFileDialog.getExistingDirectory(self, "select Directory")
        self.dataset_dir = directory_path

    # 결과폴더 선택
    def resultDir(self):
        file_path = QFileDialog.getExistingDirectory(self, "select Directory")
        self.result_dir = file_path
        print(self.result_dir)
        self.model_file_system = QFileSystemModel()
        self.model_file_system.setRootPath(file_path)
        self.model_file_system.setReadOnly(False)
        self.treeView_2.setModel(self.model_file_system)
        self.treeView_2.setRootIndex(self.model_file_system.index(file_path))
        self.treeView_2.doubleClicked.connect(lambda index: self.treeViewDoubleClicked2(index))
        self.treeView_2.setDragEnabled(True)
        self.treeView_2.setColumnWidth(0, 300)

    def reset(self):
        self.label.clear()
        self.label_2.clear()
        self.lineEdit_area.clear()
        self.lineEdit_margin.clear()
        self.margin = 15
        self.area = 1000

    def marginC(self):
        text = self.lineEdit_margin.text()
        self.margin = text

    def areaC(self):
        text = self.lineEdit_area.text()
        self.area = text



    def numberDetection(self, pyqtExceptionHandler=None):
        src = cv2.imread(self.original_img)
        gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
        gray = 255 - gray

        kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
        gray = cv2.dilate(gray, kernel, iterations=1)

        ret_val, binImg = cv2.threshold(gray, 100, 255, cv2.THRESH_OTSU)
        ret_val, gray = cv2.threshold(gray, 94, 255, cv2.THRESH_TOZERO)
        n_blob, labelImg, stats, centroid = cv2.connectedComponentsWithStats(binImg)
        model = tf.keras.models.load_model("cnn_model.h5")

        result = []
        margin = self.margin
        try:
            for i in range(1, n_blob):
                x, y, w, h, area = stats[i]

                if area > (self.area):
                    x -= margin
                    y -= margin
                    w += margin * 2
                    h += margin * 2
                    cv2.rectangle(src, (x, y, w, h), (255, 0, 255), thickness=2)

                    crop = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10))
                    crop = gray[y:y + h, x:x + w].copy()
                    crop2 = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10))
                    crop2 = src[y:y + h, x:x + w].copy()

                    crop = cv2.resize(crop, (28, 28), interpolation=cv2.INTER_AREA)
                    crop2 = cv2.resize(crop2, (28, 28), interpolation=cv2.INTER_AREA)

                    input_x = np.expand_dims(crop, axis=0)
                    output_y = model.predict(input_x)

                    ans = output_y.argmax()
                    conf = output_y[0, ans]
                    show_str = str(ans)
                    print(show_str)
                    result.append(show_str)
                    cv2.putText(src, show_str, (x, y), cv2.FONT_HERSHEY_PLAIN, 2, (0, 255, 0), 2)
                    # cv2.imwrite(f'{self.result_dir}/{i - 1}result_{show_str}.png', crop)
                    cv2.imwrite(f'{self.result_dir}/{i - 1}result_{show_str}.png', crop2)
        except Exception as e:
            print(self, f'Error : {str(e)}')

        cv2.imwrite(f'{self.result_dir}/{result}.png', src)

        # 오류처리
        sys.excepthook = pyqtExceptionHandler

        # cv2.imshow("crop ing", crop)
        # cv2.imshow("gray img", gray)
        cv2.imshow("original img", src)
        # cv2.imshow("binary img", binImg)
        cv2.waitKey(0)
        cv2.destroyAllWindows()



#   ----------------------------↑↑↑함수들↑↑↑-----------------------------------

if __name__ == "__main__" :
    app = QApplication(sys.argv)
    myWindow = WindowClass()
    myWindow.show()
    app.exec_()

 

Python 을통해 손글씨 이미지에서 숫자를 검출하는 하는 과정을 PyQt 를 통해 GUI로 제작

 

1. 이미지가 들어있는 폴더를 선택하면 오른쪽의 탐색창에 파일들이 표시되며, 탐색창에서 검출 할 이미지를 선택
2. 숫자검출 버튼을 누르면 검출 시작, 오른쪽 탐색창의 결과텝에서 파일들을 확인 할 수 있음.
3. 검출이 잘 되지 않을 떄에는 오른쪽 아래의 margin과 area를 조절해서 검출 결과를 더 좋게 수정 할 수 있음.

 

 

728x90
반응형

'정보 > Python' 카테고리의 다른 글

Python PyQt  (4) 2024.09.27
Python 손글씨 검출  (6) 2024.09.27
python YOLOv5 사용방법  (2) 2024.09.27
python 기초2  (0) 2023.01.10
python 기초1  (0) 2023.01.09
728x90
반응형

 

 

안녕하세요! 오늘은 Python을 활용해서 손글씨를 검출하는 방법에 대해 알아보려고 해요. 손글씨 인식은 요즘 인공지능 기술이 발전하면서 많은 관심을 받고 있는 분야 중 하나인데요, 특히 TensorFlow와 NumPy를 사용하면 손글씨 이미지를 쉽게 처리할 수 있어요. 그럼 시작해볼까요?

1. 손글씨 검출이란?
손글씨 검출은 사람이 쓴 글씨를 컴퓨터가 인식하는 기술이에요. 이 기술은 주로 이미지 처리와 머신러닝을 기반으로 하며, 다양한 분야에서 활용되고 있어요. 예를 들어, 우편물 분류, 자동 채점 시스템, 그리고 개인화된 학습 도구 등에서 사용되죠.

2. 필요한 라이브러리 설치하기
손글씨 검출을 위해서는 몇 가지 라이브러리를 설치해야 해요. 가장 먼저 TensorFlow와 NumPy를 설치해볼게요. 아래의 명령어를 터미널에 입력해 주세요.

bash
pip install tensorflow numpy

이 외에도 OpenCV를 사용하면 이미지 전처리에 유용하니, 필요하다면 설치해 주세요.

bash
pip install opencv-python

3. 데이터셋 준비하기
손글씨 인식을 위해서는 데이터셋이 필요해요. MNIST 데이터셋은 손글씨 숫자 이미지로 구성되어 있어, 손글씨 인식 모델을 학습하는 데 많이 사용돼요. TensorFlow에서는 이 데이터셋을 쉽게 불러올 수 있어요.

python
import tensorflow as tf

mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()

이렇게 하면 학습용 데이터와 테스트용 데이터가 준비돼요. 데이터는 28x28 픽셀의 흑백 이미지로 구성되어 있어요.

4. 모델 구축하기
이제 모델을 구축해볼게요. 간단한 신경망 모델을 만들어 보겠습니다.

python
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation='softmax')
])

여기서 Flatten 레이어는 2D 이미지를 1D 배열로 변환해주고, Dense 레이어는 완전 연결층을 의미해요. 마지막 레이어는 10개의 클래스를 분류하기 위해 softmax 활성화 함수를 사용해요.

5. 모델 학습하기
모델을 컴파일하고 학습을 시작해볼게요.

python
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])

model.fit(x_train, y_train, epochs=5)

여기서 optimizer는 Adam을 사용하고, 손실 함수는 sparse categorical crossentropy를 사용해요. epochs는 학습할 횟수를 의미해요.

6. 손글씨 이미지 검출하기
모델이 학습이 끝났다면, 이제 손글씨 이미지를 검출해볼 차례예요. 테스트 데이터셋을 사용해 모델의 성능을 확인해보겠습니다.

python
test_loss, test_acc = model.evaluate(x_test, y_test)
print('\n테스트 정확도:', test_acc)

이렇게 하면 모델의 정확도를 확인할 수 있어요. 만약 직접 손글씨 이미지를 검출하고 싶다면, OpenCV를 사용해 이미지를 불러오고 전처리한 후 모델에 입력하면 돼요.

7. 결과 확인하기
모델의 예측 결과를 확인해보는 것도 중요해요. 아래의 코드를 사용해 예측 결과를 시각화해볼 수 있어요.

python
import matplotlib.pyplot as plt

predictions = model.predict(x_test)

for i in range(5):
plt.imshow(x_test[i], cmap='gray')
plt.title(f'예측: ')
plt.show()

이렇게 하면 예측한 숫자와 실제 숫자를 비교할 수 있어요. 시각적으로 확인하는 것이 많은 도움이 될 거예요.

8. 마무리 및 추가 자료
오늘은 Python과 TensorFlow를 사용하여 손글씨를 검출하는 방법에 대해 알아보았어요. 손글씨 인식은 다양한 분야에서 활용될 수 있는 유용한 기술이니, 여러분도 한번 도전해보세요! 추가적으로 더 깊이 있는 학습을 원하신다면, TensorFlow 공식 문서나 관련 블로그를 참고하시면 좋을 것 같아요.

이상으로 손글씨 검출에 대한 포스팅을 마치겠습니다. 궁금한 점이 있다면 댓글로 남겨주세요!

728x90
반응형

'정보 > Python' 카테고리의 다른 글

Python 손글씨 검출 GUI  (0) 2024.09.27
Python PyQt  (4) 2024.09.27
python YOLOv5 사용방법  (2) 2024.09.27
python 기초2  (0) 2023.01.10
python 기초1  (0) 2023.01.09

+ Recent posts

728x90
반응형
">