Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 13, 2025 15:26:14

gps38region
Зарегистрирован: 2025-01-13
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Python + Arduino (Управление Servo+Arduino из Python+OpenCV)

Приветствую всех ГУРУ и тех кому не безразлична данная тема.

Пытаюсь сделать трекер лица Python+OpenCV –> Arduino+Servo

Для Ардуино написал скетч который по СОМ порту принимает команду в формате X:Y (0:0 , 180:180 , 23:56 и т.д.)

 #include <Servo.h>
Servo servo[2];  // объект серво для 2х моторов
 
void setup() {
  Serial.begin(9600);  // открыть порт для связи
  servo[0].attach(7, 400, 2400);
  servo[1].attach(8, 400, 2400);
 
  servo[0].write(90); //выводим серво в центр
  servo[1].write(90); //выводим серво в центр
}
 
void loop() {  // Основной цикл
 
  if (Serial.available() > 0) {  // если что то прислали
 
    String bufString = Serial.readString();                // читаем как строку
    byte dividerIndex = bufString.indexOf(':');            // ищем индекс разделителя
    String buf_1 = bufString.substring(0, dividerIndex);   // создаём строку с первым числом
    String buf_2 = bufString.substring(dividerIndex + 1);  // создаём строку со вторым числом
    int val_1 = buf_1.toInt();                             // преобразуем угол горизонталм
    int val_2 = buf_2.toInt();                             // преобразуем угол вертикали
 
    servo[0].write(val_1); // поворот по X
    servo[1].write(val_2); // поворот по Y
    delay(100);
  }
}
Написал на Python проверочный код и все повороты 100% отрабатывают но с какой то задержкой…

 import time
import serial
 
# Configure the COM port
port = "COM8"  # Replace with the appropriate COM port name
baudrate = 9600
# Open the COM port
ser = serial.Serial(port, baudrate=baudrate)
print("Serial connection established.")
 
try:
 
    # Send commands to the Arduino
    while True:
        
        command = input("Enter a command ('0:0', '180:180'): ")
        ser.write(command.encode())
        
except KeyboardInterrupt:
    pass
 
finally:
    # Close the serial connection
    if ser.is_open:
        command = '0:0' # zero position
        ser.write(command.encode())
        ser.close()
        print("Serial connection closed.")

А вот код на Python который через OpenCV определяет центр лица и смещения по X Y отправляет через СОМ порт на Arduino в формате как в тестовом коде…..

 import numpy as np
import cv2
 
import serial
port = "COM8"  # Replace with the appropriate COM port name
baudrate = 9600
# Open the COM port
arduino = serial.Serial(port, baudrate=baudrate)
 
 
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_eye.xml')
    
capture = cv2.VideoCapture(0,cv2.CAP_DSHOW)
#capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1024)
#capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
 
Tim=0
 
xi = int(capture.get(3))
cxi = int(xi/2)
yi = int(capture.get(4))
cyi = int(yi/2)
 
while True:
    ret, frame = capture.read()
    
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)
    eyes = eye_cascade.detectMultiScale(gray, 1.3, 5)
 
    cv2.line(frame, (cxi,0),(cxi,yi),(120,120,120),1)
    cv2.line(frame, (0,cyi),(xi,cyi),(120,120,120),1)
    ct = ''
 
    for (x, y, w, h) in faces:
        frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 255), 2)
        cx=int(x+w/2)
        cy=int(y+h/2)
        dx=int(90+cxi-cx)
        dy=int(90+cyi-cy)
        ct=str(dx)+':'+str(dy) # Send to COM port
        cv2.circle(frame, (cx,cy), 5, (0, 0, 255) , -1) #-1 
        cv2.line(frame, (cxi,cyi), (cx,cy),(0, 0, 255), 3)
 
        cv2.putText(frame, ct, (0, 20), cv2.FONT_HERSHEY_DUPLEX, 0.9, (0, 0, 250), 1) 
        # Send commands to the Arduino
 
        # ser.write(f"{angle}n".encode())
        command = ct #input('Enter a command (e.g., 'ON', 'OFF'): ')
        arduino.write(command.encode())
        #print(command)
 
    cv2.imshow('From Camera', frame)
 
    k = cv2.waitKey(30) & 0xFF
    if k == 27:
        if arduino.is_open:
          command = '0:0'
          arduino.write(command.encode())
          arduino.close()
          print("Serial connection closed.")
        break
 
capture.release()
cv2.destroyAllWindows()

Видео отображает, смещения вычисляются…
Но Servo на Arduino не отрабатывает практически НИ КАК…
Бывают иногда какието дергания Servo , Но это не то что я хотел (отслеживать движение лица и поворачивать камеру)

Подскажите , где у меня ошибка и куда копать ???
Заранее благодарю за помощь…

Отредактировано gps38region (Янв. 13, 2025 15:28:48)

Офлайн

#2 Янв. 13, 2025 16:31:27

xam1816
Зарегистрирован: 2020-05-11
Сообщения: 1370
Репутация: +  121  -
Профиль   Отправить e-mail  

Python + Arduino (Управление Servo+Arduino из Python+OpenCV)

gps38region
Но Servo на Arduino не отрабатывает практически НИ КАК…
  
arduino.write(command.encode())  # Отправка команды
arduino.flush()  # Убедитесь, что данные отправлены
time.sleep(0.1) # Сделать задержку

Офлайн

#3 Янв. 13, 2025 16:55:03

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2756
Репутация: +  184  -
Профиль   Отправить e-mail  

Python + Arduino (Управление Servo+Arduino из Python+OpenCV)

Покажи вывод переменной ct



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#4 Янв. 14, 2025 13:11:27

gps38region
Зарегистрирован: 2025-01-13
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Python + Arduino (Управление Servo+Arduino из Python+OpenCV)

xam1816
Но Servo на Arduino не отрабатывает практически НИ КАК…
Когда вручную отправляю то серво отрабатывает все как нужно.

Вот код ручного …

import time
import serial

# Configure the COM port
port = "COM8" # Replace with the appropriate COM port name
baudrate = 9600
# Open the COM port
ser = serial.Serial(port, baudrate=baudrate)
print("Serial connection established.")

try:

# Send commands to the Arduino
while True:

command = input("Enter a command ('0:0', '180:180'): ")
ser.write(command.encode())

except KeyboardInterrupt:
pass

finally:
# Close the serial connection
if ser.is_open:
command = '0:0' # zero position
ser.write(command.encode())
ser.close()
print("Serial connection closed.")

Исправил как подсказали….
arduino.write(command.encode())  # Отправка команды
arduino.flush() # Убедитесь, что данные отправлены
time.sleep(0.1) # Сделать задержку
Результат тот же…. Не отрабатывает…

Отредактировано gps38region (Янв. 14, 2025 13:15:35)

Офлайн

#5 Янв. 14, 2025 13:13:26

gps38region
Зарегистрирован: 2025-01-13
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Python + Arduino (Управление Servo+Arduino из Python+OpenCV)

Rodegast
Покажи вывод переменной ct

command = ct
arduino.write(command.encode())

Офлайн

#6 Янв. 14, 2025 13:45:18

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2756
Репутация: +  184  -
Профиль   Отправить e-mail  

Python + Arduino (Управление Servo+Arduino из Python+OpenCV)

gps38region Добавь print(ct) и покажи что он печатает.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#7 Янв. 14, 2025 14:34:32

gps38region
Зарегистрирован: 2025-01-13
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Python + Arduino (Управление Servo+Arduino из Python+OpenCV)

Rodegast
Добавь print(ct) и покажи что он печатает.


 for (x, y, w, h) in faces:
        frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 255), 2)
            cx=int(x+w/2)
        cy=int(y+h/2)
        dx=int(90+cxi-cx)
        dy=int(90+cyi-cy)
        ct=str(dx)+':'+str(dy) # Send to COM port
        cv2.circle(frame, (cx,cy), 5, (0, 0, 255) , -1) #-1 
        cv2.line(frame, (cxi,cyi), (cx,cy),(0, 0, 255), 3)
        cv2.putText(frame, ct, (0, 20), cv2.FONT_HERSHEY_DUPLEX, 0.9, (0, 0, 250), 1) 
        # Send commands to the Arduino
        #print(current_time0)
        #if (time.time()-current_time0)>2.0:
          # ser.write(f"{angle}n".encode())
        print(ct)
        command = ct
        arduino.write(command.encode())
        arduino.flush() 
        time.sleep(1.2)

Печатает в консоли :

E:\Python>Camera.py
157:181
160:175
165:180
196:146
connection closed.

Отредактировано gps38region (Янв. 14, 2025 14:40:27)

Офлайн

#8 Янв. 14, 2025 14:38:05

gps38region
Зарегистрирован: 2025-01-13
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Python + Arduino (Управление Servo+Arduino из Python+OpenCV)


Скрин

Отредактировано gps38region (Янв. 14, 2025 14:38:49)

Прикреплённый файлы:
attachment 01.PNG (16,7 KБ)

Офлайн

#9 Янв. 14, 2025 17:29:32

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2756
Репутация: +  184  -
Профиль   Отправить e-mail  

Python + Arduino (Управление Servo+Arduino из Python+OpenCV)

> Печатает в консоли

У тебя некоторые значения превышают 180 т.е. больше крайних положений. Это норм? Посмотри с какой скоростью идут данные, возможно он у тебя не успевает повернутся. Поставь что то вроде time.sleep(3) после каждой записи в порт и посмотри что изменится.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Отредактировано Rodegast (Янв. 14, 2025 17:29:46)

Офлайн

#10 Янв. 15, 2025 12:27:39

gps38region
Зарегистрирован: 2025-01-13
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Python + Arduino (Управление Servo+Arduino из Python+OpenCV)

Rodegast
У тебя некоторые значения превышают 180 т.е. больше крайних положений. Это норм? Посмотри с какой скоростью идут данные, возможно он у тебя не успевает повернутся. Поставь что то вроде time.sleep(3) после каждой записи в порт и посмотри что изменится.
1. Значения некоторые действительно больше 180, но это не принципиально так как при значениях от 0 до 180 , та же песня вернее молчание сервы.
2. В тестовой посылке выяснил что серва начинает отрабатывать при отправке команд не чаще 1.1 секунды. Ставлю 1.05 и срабатывает через раз (не 0-30-60-90-120-150-180 а 0-60-120-180 и то не всегда). Минимальное время отправки 1.1 секунда, что очень много для реального отслеживания через OpenCV
3. Буду для начала организовывать таймер на 1.1-1.2 сек, посмотрю как получится….
Отпишусь позже…..

P.S. Не думал что скорость работы Питона с СОМ портом такое тормознутое…
Пока вывод такой…

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version