Vision AI 기반 제조 자동화 검수 시스템

kikiru328 | Dec 8, 2022 min read

Python PyTorch YOLOv5 OpenCV PyQt5

한 장 요약본

프로젝트 개요

목록내용
프로젝트명Vision AI 기반 제조 자동화 검수 시스템
개발기간2022년 10월 - 2022년 12월 (2개월)
역할AI Solution 개발자 (직접 기획, 설계 및 구현)
기여도90% (1인 개발, 제조 담당자 데이터 검수 협업)
개발환경로컬 환경, 웹캠 4대, PyQt5 독립 실행

비즈니스 배경 및 문제 정의

핵심과제

커스터마이징 간편식 제조 과정의 스티커 라벨링 비효율성 및 옵션 누락 문제 해결

제조 환경:

  • 4단계 제조 카운터: 용기 → 채소 → 옵션 → 포장 (사람이 카운터에서 단계별 진행)
  • 커스터마이징 옵션: 개인 취향별 재료 제외 (당근X, 오이X 등)
  • 일일 제조량: 100-200개 제품 생산

기존 프로세스 문제점:

  • 스티커 라벨링 비효율성: 용기마다 개별 라벨 부착 작업으로 시간 소요
  • 옵션 누락 빈발: 하루 100-200개 제조 시 옵션 누락 사례 다수 발생
  • 수작업 카운팅 오류: 제조 담당자 수동 카운팅으로 인한 실수
  • 복잡한 옵션 순서: 제조 목록 순서 추적 어려움으로 혼란 야기
  • 네트워크 제약: 웹 기반 시스템 사용 불가한 제조 현장 환경

핵심 성과 지표

지표달성값측정 방법
객체 탐지 정확도0.65 → 0.8+mAP@0.5 기준 23% 성능 향상
실시간 처리 성능<1초 지연YOLOv5s + DeepSORT 최적화
다중 웹캠 지원최대 4개멀티스레딩 기반 병렬 처리
환경 적응성제조 환경 변화 대응조명, 재료 적재 상태 변화 robust

기술 스택 및 아키텍처

핵심 기술 스택

# 주요 기술 구성
Object Detection: YOLOv5s      # 경량화된 실시간 용기 탐지
Object Tracking : DeepSORT     # 개별 용기 추적 및 ID 관리
Image Processing: OpenCV       # 영상 처리 및 전처리
GUI Framework   : PyQt5        # 독립 실행 데스크톱 앱
Deployment      : Pyinstaller  # .exe 패키징으로 로컬 대응
Data Processing : NumPy, Pandas

시스템 아키텍처

  graph TD
    A[웹캠 영상 입력] --> B[YOLOv5s 객체 탐지]
    B --> C[DeepSORT 객체 추적]
    C --> D[중앙선 교차 감지]
    D --> E[방향성 카운팅]
    E --> F[제조 목록 매칭]
    F --> G[옵션 안내 표시]
    G --> H[실시간 진행 상황]
    
    I[제조 목록 업로드] --> F
    J[4개 웹캠 병렬 처리] --> A
    K[PyQt5 GUI] --> H

주요 기술적 도전과 해결책

1. 제조 환경 변화에 robust한 객체 탐지

도전과제

  • 초기 성능: 객체 탐지 정확도 0.65 (mAP@0.5 기준)
  • 환경 변수: 조명 변화, 재료 적재 상태, 제조 환경에 따른 탐지 성능 저하
  • 데이터 제약: 제한된 학습 데이터로 다양한 환경 조건 학습 어려움

문제 해결 과정

1단계: 실제 제조 환경 데이터 수집

# 데이터 수집 전략
data_collection_strategy = {
    "영상 수": 50개,
    "프레임 추출": "약 400장 BBox 라벨링",
    "환경 조건": [
        "아침/점심/저녁 조명 변화",
        "재료 적재 상태 변화", 
        "제조 카운터 위치별 각도",
        "용기 종류별 (빈 용기 ~ 완성품)"
    ]
}

2단계: 제조진 협업 기반 라벨링 품질 향상

  • 도메인 전문가 검수: 제조 담당자와 협업으로 정확한 객체 구분
  • 프레임별 세밀한 분석: 영상을 프레임 단위로 분할하여 상황별 라벨링
  • 품질 검증: 제조진 직접 검수로 라벨링 정확도 확보

3단계: YOLOv5s 모델 최적화

# YOLOv5s 학습 설정
training_config = {
    "model": "YOLOv5s",           # 실시간 처리를 위한 경량 모델
    "epochs": 300,
    "batch_size": 16,
    "img_size": 640,
    "data": "container_dataset.yaml",
    "weights": "yolov5s.pt"       # 사전 학습된 가중치
}

# 데이터셋 구성
dataset_structure = {
    "train": "400장 (80%)",
    "val": "100장 (20%)",
    "classes": ["empty_container", "filled_container", "completed_product"]
}
성과
  • 정확도 향상: 0.65 → 0.8+ 달성 (mAP@0.5 기준, 23% 이상 개선)
  • 환경 적응성: 다양한 조명 및 재료 상태에서 안정적 탐지
  • 실시간 성능: <1초 지연으로 제조 속도에 맞춘 처리

2. 실시간 객체 추적 및 방향성 카운팅

도전과제

  • 움직이는 객체 추적: 제조 카운터에서 이동하는 용기의 정확한 추적
  • 역방향 오카운팅 방지: 용기가 역방향으로 움직일 때 잘못된 카운팅 방지
  • 실시간 성능: 초기 1초 딜레이 문제로 제조 속도 저해

문제 해결 과정

alt text

1단계: YOLOv5s + DeepSORT 통합 시스템
2단계: 추적 ID 관리 시스템

# OCP, 객체 중앙점 설정
    def box_label(self, box, label='', color=(128, 128, 128), txt_color=(255, 255, 255)):
        # Add one xyxy box to image with label
        if self.pil or not is_ascii(label):
            self.draw.rectangle(box, width=self.lw, outline=color)  # box
            if label:
                w, h = self.font.getsize(label)  # text width, height
                outside = box[1] - h >= 0  # label fits outside box
                self.draw.rectangle(
                    (box[0], box[1] - h if outside else box[1], box[0] + w + 1,
                     box[1] + 1 if outside else box[1] + h + 1),
                    fill=color,
                )
                # self.draw.text((box[0], box[1]), label, fill=txt_color, font=self.font, anchor='ls')  # for PIL>8.0
                self.draw.text((box[0], box[1] - h if outside else box[1]), label, fill=txt_color, font=self.font)
        else:  # cv2
            p1, p2 = (int(box[0]), int(box[1])), (int(box[2]), int(box[3]))
            center_coordinates = (int(box[0] + (box[2]-box[0])/2), int(box[1] + (box[3] - box[1])/2))
            cv2.rectangle(self.im, p1, p2, color, thickness=self.lw, lineType=cv2.LINE_AA)
            cv2.circle(self.im, center_coordinates, radius=3, color=color, thickness=3)
            if label:
                tf = max(self.lw - 1, 1)  # font thickness
                w, h = cv2.getTextSize(label, 0, fontScale=self.lw / 3, thickness=tf)[0]  # text width, height
                outside = p1[1] - h >= 3
                p2 = p1[0] + w, p1[1] - h - 3 if outside else p1[1] + h + 3
                cv2.rectangle(self.im, p1, p2, color, -1, cv2.LINE_AA)  # filled
                cv2.putText(self.im,
                            label, (p1[0], p1[1] - 2 if outside else p1[1] + h + 2),
                            0,
                            self.lw / 3,
                            txt_color,
                            thickness=tf,
                            lineType=cv2.LINE_AA
#개수판단
class Count:
    def count_1_function(det, im, s, im0, names, outputs, tracker_list, dt, i, t3,t2,tracking_method,annotator, save_txt, txt_path,frame_idx, save_vid, save_crop, show_vid, hide_labels, hide_conf, hide_class, path, imc, save_dir, p):
        w, h = im0.shape[1], im0.shape[0]
        if det is not None and len(det):
            det[:, :4] = scale_coords(im.shape[2:], det[:, :4], im0.shape).round()
            for c in det[:, -1].unique():
                n = (det[:, -1] == c).sum()  # detections per class
                s += f"{n} {names[int(c)]}{'s' * (n > 1)}, "
            t4 = time_sync()
            outputs[i] = tracker_list[i].update(det.cpu(), im0)
            t5 = time_sync()
            dt[3] += t5 - t4
            if len(outputs[i]) > 0:
                for j, (output, conf) in enumerate(zip(outputs[i], det[:, 4])):
                    bboxes = output[0:4]
                    id = output[4]
                    cls = output[5]
                    global count_web_1, data_web_1, order_index_web_1, step_count_web_1
                    center_coordinates = (
                        int(bboxes[0] + (bboxes[2]-bboxes[0])/2), int(bboxes[1] + (bboxes[3] - bboxes[1])/2))
                    
                    if (int(bboxes[0]+(bboxes[2] - bboxes[0])/2) < (int(w/2))) and (id not in data_web_1):

                        # like sensor
                        im0 = cv2.rectangle(im0, (0,0), (w,h), (0,0,255), -1)
                        
                        count_web_1 += 1
                        data_web_1.append(id)
                        order_data_count = order_data['Count']
                        step_count_web_1 += 1
                        
                        if step_count_web_1 >= int(order_data_count[order_index_web_1]):
                            order_index_web_1+= 1
                            step_count_web_1 = 0 
                            
                    common_save_functions(output, save_txt, txt_path, frame_idx, i, save_vid, save_crop, show_vid, id, cls,hide_labels, names, hide_conf, conf, hide_class, annotator, bboxes, path, imc, save_dir, p)
                    
            # LOGGER.info(f'{s}Done. yolo:({t3 - t2:.3f}s), {tracking_method}:({t5 - t4:.3f}s)')
        else:
            # strongsort_list[i].increment_ages()
            # LOGGER.info('No detections')    
            pass
        im0 = annotator.result()
        return im0, count_web_1, order_index_web_1, step_count_web_1

3단계: 성능 최적화

  • 경량화 모델: YOLOv5s 선택으로 추론 속도 향상
  • 효율적 추적: DeepSORT 파라미터 튜닝으로 ID 스위칭 최소화
  • 멀티스레딩: 각 웹캠별 독립 처리로 병렬 성능 확보
성과
  • 정확한 카운팅: 좌→우 단방향 카운팅으로 역방향 오류 방지
  • 실시간 처리: 1초 딜레이 해결로 제조 속도에 맞춘 시스템
  • 안정적 추적: 객체 ID 관리로 중복 카운팅 방지

3. 로컬 환경 대응 독립 실행 시스템

도전과제

  • 네트워크 제약: 제조 현장에서 웹 기반 시스템 사용 불가
  • 외부 의존성: 클라우드 서비스나 외부 API 연결 불가능
  • 배포 복잡성: 별도 서버 설치나 복잡한 환경 설정 어려움

문제 해결 과정

1단계: PyQt5 네이티브 애플리케이션 개발
2단계: Pyinstaller 기반 .exe 패키징
3단계: 로컬 완전 독립 처리

  • 모든 연산 로컬 처리: AI 모델 추론부터 결과 표시까지 완전 오프라인
  • 설정 파일 로컬 저장: 제조 목록 및 옵션 설정을 로컬 파일로 관리
  • 결과 데이터 로컬 저장: 처리 결과 및 로그를 로컬 폴더에 저장
성과
  • 완전 독립 실행: 네트워크 연결 없이 모든 기능 작동
  • 간편 배포: .exe 파일 하나로 설치 및 실행 완료
  • 로컬 사용: 외부 연결 없이 로컬 환경에서 안전한 사용

4. 직관적 제조 진행 상황 시각화

도전과제

  • 복잡한 옵션 관리: 다양한 커스터마이징 옵션을 제조진이 쉽게 파악 필요
  • 실시간 진행 표시: 현재 제조 상황과 다음 단계를 명확히 안내
  • 비개발자 사용성: 제조 담당자가 직관적으로 이해할 수 있는 인터페이스

문제 해결 과정

alt text alt text

1단계: 색상 기반 직관적 시각화
2단계: 실시간 카운터 및 진행 상황 표시
3단계: 다중 옵션 동시 표시

  • 화면 분할: 여러 옵션을 동시에 표시할 수 있는 유연한 레이아웃
  • 우선순위 표시: 현재 진행 중인 옵션을 강조 표시
  • 히스토리 표시: 완료된 옵션 목록을 별도 영역에 표시
성과
  • 직관적 이해: 색상 기반 표시로 제조진이 즉시 상황 파악 가능
  • 실시간 안내: 현재와 다음 단계를 명확히 제시하여 혼란 방지
  • 사용자 친화성: 비개발자도 교육 없이 바로 사용 가능한 인터페이스

5. 다중 웹캠 연동 및 성능 최적화

도전과제

  • 4단계 제조 라인: 각 제조 단계별 독립 웹캠으로 전체 프로세스 모니터링
  • 성능 한계: 다중 스트림 처리 시 하드웨어 리소스 제약
  • 동기화: 각 단계별 처리 결과를 실시간으로 통합 관리

문제 해결 과정

1단계: 멀티스레딩 기반 병렬 처리
2단계: 리소스 최적화 및 성능 한계 확인
3단계: 중앙 집중식 결과 통합

성과
  • 다중 스트림 지원: 최대 4개 웹캠 동시 처리로 전체 제조 라인 모니터링
  • 성능 한계 명확화: 4개 이상 시 성능 저하 발생 확인 및 사용자 안내
  • 안정적 운영: GPU/CPU 리소스 효율 분배로 시스템 안정성 확보

성능 평가 및 검증

객체 탐지 성능

  • Before: mAP@0.5 기준 0.65
  • After: mAP@0.5 기준 0.8+ 달성
  • 개선율: 23% 이상 성능 향상

실시간 처리 성능

  • 지연 시간: <1초 (제조 카운터 속도에 맞춘 실시간 처리)
  • 처리 안정성: 연속 8시간 운영 시 오류 없음
  • 다중 스트림: 4개 웹캠 동시 처리 시 안정적 성능 유지

비즈니스 임팩트 및 성과

효율성 향상

  • 스티커 라벨링 제거: 용기별 개별 라벨 부착 작업 완전 자동화
  • 옵션 누락 방지: 하루 100-200개 제조 시 누락 사례 대폭 감소
  • 제조 집중도 향상: 수작업 카운팅 부담 제거로 제조 품질에 집중

품질 관리 강화

  • 실시간 모니터링: 제조 진행 상황 실시간 추적으로 품질 일관성 확보
  • 오류 사전 방지: 잘못된 옵션 진행 시 즉시 알림으로 재작업 방지

기술적 가치 창출

  • 실용적 솔루션: 실제 제조 환경의 제약 조건을 모두 고려한 실무 적용 가능 시스템
  • 확장 가능성: 다양한 제조 환경에 적용 가능한 모듈화된 아키텍처

기술적 학습 및 성장

Computer Vision 전문성

  • 객체 탐지: YOLO 모델 최적화 및 실제 환경 적용 경험
  • 객체 추적: DeepSORT 기반 다중 객체 추적 시스템 구현
  • 실시간 처리: 제조 환경에서 요구되는 실시간 성능 최적화
  • 데이터 수집: 실제 환경에서의 효과적 학습 데이터 구축 방법론

제조 도메인 이해

  • 현장 중심 개발: 실제 제조 환경의 변수(조명, 재료 상태)를 충분히 고려한 robust한 모델 개발
  • 도메인 협업: 제조 담당자와의 협업을 통한 데이터 품질 향상 및 실용성 확보
  • 프로세스 최적화: 기존 제조 워크플로우 분석 및 AI 기술 적용 방안 도출
  • 사용자 중심 설계: 비개발자도 직관적으로 사용할 수 있는 인터페이스 설계

시스템 엔지니어링 역량

  • 독립 실행 시스템: 네트워크 제약이 있는 환경에서의 완전 독립적 AI 시스템 구축
  • 멀티스레딩: 다중 웹캠 병렬 처리를 위한 효율적 스레드 관리
  • 리소스 최적화: 제한된 하드웨어 리소스에서 최대 성능 달성을 위한 최적화
  • GUI 개발: PyQt5 기반 사용자 친화적 데스크톱 애플리케이션 개발

제약 조건 하에서의 창의적 해결

  • 로컬 환경: 외부 연결 불가 환경에서 완전 독립적 시스템 구축
  • 실시간 성능: 제조 속도에 맞춘 <1초 지연 달성
  • 하드웨어 제약: 제한된 GPU/CPU 리소스에서 4개 웹캠 동시 처리
  • 사용성: 복잡한 AI 시스템을 제조진이 쉽게 사용할 수 있도록 단순화

프로젝트 관리 및 협업

도메인 전문가 협업

  1. 요구사항 분석: 제조진과의 지속적 소통으로 실제 현장 문제 파악
  2. 데이터 검수: 제조 담당자 직접 참여로 라벨링 품질 향상
  3. 테스트 협업: 실제 제조 환경에서의 시스템 검증 및 피드백 수집
  4. 사용성 개선: 현장 사용자 관점에서 인터페이스 지속 개선

기술적 문서화

  1. 구현 문서: 각 컴포넌트별 기술 사양 및 최적화 내용 상세 기록
  2. 사용자 매뉴얼: 제조진 대상 시스템 사용법 및 문제 해결 가이드

결론 및 시사점

기술적 가치

  • 실무 적용 AI: 실제 제조 환경의 모든 제약 조건을 고려한 실용적 AI 솔루션
  • 독립 실행 시스템: 외부 의존성 없이 완전 독립적으로 작동하는 AI 시스템 구축 경험
  • 실시간 처리: 제조 현장에서 요구되는 실시간 성능 달성 기술

개발자로서의 성장

  • 현장 중심 사고: 기술적 완성도보다 실제 사용자의 문제 해결에 집중
  • 제약 조건 극복: 한정된 자원과 환경에서 창의적 해결책 도출 능력
  • 도메인 협업: 비개발자와의 효과적 소통 및 협업을 통한 가치 창출
  • 실용성 우선: 복잡한 기술보다 실제로 작동하는 솔루션 개발 역량