목차

  1. 프로젝트 소개

    1. 프로젝트 배경 및 목적

      1. 왜 쓰레기 분류가 중요한지 설명

        (1) 자원 절약

        (2) 환경 오염 감소

        (3) 온실가스 배출 감소

        image.png

      2. 이 시스템을 통해 해결하자고 하는 문제

        (1) 사람들이 분리수거를 할 때, 재활용 방법을 잘 몰라서 안하는 경우가 존재

        image.png

        image.png

      (2) 또한 본인에게 직접적으로 돌아오는게 없어서 안함

      (3) 이러한 문제를 자동 분리수거를 이용하여 해결

  2. 시스템 설계

    1. 하드웨어 구성 요소 설명(LED, 초음파, 서보 모터, DC 모터 etc)
      1. LED
      2. 초음파 센서
      3. 서보 모터
      4. 카메라 모듈
      5. DC 모터
      6. lcd
  3. 알고리즘 및 코드

    1. 시스템 주요 알고리즘

      1. 초음파 센서를 이용한 물체 감지

        (알고리즘 단순하게 정리)

      2. cv를 통한 물체 분류

      3. 서보 모터를 이용한 쓰레기 분류 동작

    2. 코드 흐름 설명

      1. 주요 함수 및 모듈에 대한 간단한 설명

        (1) 초음파 센서 함수

        def get_distance(pin):
            try:
                distance = grovepi.ultrasonicRead(pin)
                return distance
            except TypeError:
                print("초음파 센서가 작동되지 않음")
                return None
        

        (2) DC 모터 함수

        # DC 모터 제어 함수
        def operate_dc_motor(speed, state):
            if state == 1:
                GPIO.output(IN1, GPIO.HIGH)
                GPIO.output(IN2, GPIO.LOW)
                pwm1.ChangeDutyCycle(speed)
        
                GPIO.output(IN3, GPIO.HIGH)
                GPIO.output(IN4, GPIO.LOW)
                pwm2.ChangeDutyCycle(speed)
            else:
                GPIO.output(IN1, GPIO.LOW)
                GPIO.output(IN2, GPIO.LOW)
                pwm1.ChangeDutyCycle(0)
        
                GPIO.output(IN3, GPIO.LOW)
                GPIO.output(IN4, GPIO.LOW)
                pwm2.ChangeDutyCycle(0)
        

        (3) 서보 모터 함수

        def move_servo(result):
            if result == 'Paper':
                grovepi.servoWrite(SERVO_PIN1, 30)
                grovepi.servoWrite(SERVO_PIN2, 120)
            elif result == 'Plastic':
                grovepi.servoWrite(SERVO_PIN1, 60)
                grovepi.servoWrite(SERVO_PIN2, 90)
            elif result == 'PET':
                grovepi.servoWrite(SERVO_PIN1, 90)
                grovepi.servoWrite(SERVO_PIN2, 60)
            elif result == 'Glass':
                grovepi.servoWrite(SERVO_PIN1, 120)
                grovepi.servoWrite(SERVO_PIN2, 30)
            time.sleep(1)
        

        (4) 쓰레기 분류

        # 쓰레기 분류 함수
        def classify_waste(input_image):
            input_hist = cv2.calcHist([input_image], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256])
            cv2.normalize(input_hist, input_hist, 0, 1, cv2.NORM_MINMAX)
        
            best_match = None
            highest_score = -1
        
            for label, ref_image in reference_images.items():
                ref_hist = cv2.calcHist([ref_image], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256])
                cv2.normalize(ref_hist, ref_hist, 0, 1, cv2.NORM_MINMAX)
                score = cv2.compareHist(input_hist, ref_hist, cv2.HISTCMP_CORREL)
        
                if score > highest_score:
                    highest_score = score
                    best_match = label
        
            return best_match
        

        (5) lcd 함수

        # I2C LCD 관련 설정
        I2C_ADDR = 0x27
        LCD_WIDTH = 16
        LCD_CHR = 1
        LCD_CMD = 0
        LCD_LINE_1 = 0x80
        LCD_LINE_2 = 0xC0
        E_DELAY = 0.0005
        
        # LCD 제어 함수
        def lcd_byte(bits, mode):
            bus.write_byte_data(I2C_ADDR, mode, bits)
            time.sleep(E_DELAY)
        
        def lcd_string(message, line):
            message = message.ljust(LCD_WIDTH, " ")
            for i in range(LCD_WIDTH):
                lcd_byte(ord(message[i]), LCD_CHR)
        
        def lcd_init():
            lcd_byte(0x33, LCD_CMD)
            lcd_byte(0x32, LCD_CMD)
            lcd_byte(0x06, LCD_CMD)
            lcd_byte(0x0C, LCD_CMD)
            lcd_byte(0x28, LCD_CMD)
            lcd_byte(0x01, LCD_CMD)
            time.sleep(E_DELAY)
        
      2. 데이터 흐름

        (1) try 안에 while 반복문 정의

        try:
            bus = smbus.SMBus(1)
            lcd_init()
        
            while True:
                # 초음파 센서 1에서 물체 감지
                if get_distance(ULTRASONIC_PIN_1) < 10:
                    operate_dc_motor(speed=50, state=1)  # 모터 작동
                    time.sleep(3)  # 이동 시간
        
                # 초음파 센서 2에서 물체 감지
                if get_distance(ULTRASONIC_PIN_2) < 10:
                    operate_dc_motor(speed=0, state=0)  # 모터 정지
        
                    # 카메라로 이미지 캡처
                    camera = cv2.VideoCapture(0)
                    ret, frame = camera.read()
                    camera.release()
        
                    if ret:
                        # 쓰레기 분류
                        result = classify_waste(frame)
                        print(f"분류 결과: {result}")
                        lcd_string("Classified as:", LCD_LINE_1)
                        lcd_string(result, LCD_LINE_2)
        
                        # 서보 모터 동작
                        move_servo(result)
        
                    time.sleep(2)
        
        except KeyboardInterrupt:
            pwm1.stop()
            pwm2.stop()
            GPIO.cleanup()
            print("프로그램 종료")
        
  4. 시스템 구현 과정

    1. 하드웨어 설치 및 조립

      (1) 설계도

    2. 분류 모델 설명

      (1) 모델 기본 설명

  5. 테스트 및 결과

    1. 실제 하드웨어 동작 과정 영상

    2. 딥러닝 분류 모델 동작 과정 영상

  6. 문제점 및 개선점

    1. 문제점

      1. 기존에 목표였던 라즈베리파이에, 모델 넣기 실패 이유

        (1) 라즈베리파이2의 하드웨어 한계로 인해 tensorflow 설치 이슈

      2. 분류 한계

        (1) 하드웨어적인 한계로 인해 너무 무겁거나 큰 물체는 분류하지 못함

        (2) 사용자가 하나하나 쓰레기를 넣어야함

    2. 대안 및 개선점

      1. cv 사용

      2. 셔틀과 배큠을 이용한 분류

        (1) 영상

  7. 결론

    1. 프로젝트 성과

    (1) 목표 달성 여부

    (2) 주요 성과


    2. 기대 효과

    (1) 환경 보호

    (2) 효율적인 쓰레기 관리

    (3) 교육적 도구로 활용 가능

    (4) 상업적 활용 가능성


    3. 한계 및 문제점

    (1) 제한된 분류 대상

  8. Q&A