2021년 프로젝트 LAB(2)
IMU 센서를 사용한 실시간 정지 영상 객체 검출 프로젝트
- PC
-
server_main.py 실행 시 아래와 같은 Pyqt5를 사용한 UI 출력함
-
서버 켜짐 버튼 클릭 시 멀티스레드를 사용한 다중 소켓 통신 대기 상태 돌입함
-
클라이언트 측에서 소켓 통신 성공 시 "클라이언트 연결 성공" 출력함
-
"클라이언트 연결 성공" 출력과 동시에 UI 왼쪽 패널에 클라이언트 측 카메라 영상 수신함
-
클라이언트 측 IMU 센서 정지 시 UI 오른쪽 패널에 정지 순간 영상 수신함
-
5번 수신과 동시에 UI 오른쪽 패널에서 Yolo를 사용한 객체 검출 결과 출력함
-
서버 꺼짐 버튼을 클릭 시 다중 소켓 연결에 종료되고 영상 수신 종료함
-
7번과 동시에 같은 디렉토리 안에 객체 검출 정보가 담긴 "Detection_sheet.xlsx" 엑셀 파일 저장함
-
2번에서 8번까지 일련의 과정을 연속해서 소켓에 할당 가능하며 프로그램 종료 버튼 클릭 시 UI가 종료 됨
- Client 라즈베리파이
-
라즈베리파이 안 Client.py 실행 시 서버 연결 대기 상태에 돌입함
-
1번 클라이언트(1번 IP와 포트), 2번 클라이언트(2번 IP와 포트)를 각각 서버에 연결함
-
서버 연결 성공 시 1번 클라이언트가 실시간 USB카메라 영상을 서버에 송신함
-
3번 후 IMU 센서 구동을 하며 자이로 값에 따른 가속도 값을 출력함
-
4번 후 시작 가속도 정보를 같은 디렉토리에 "start.txt" 파일을 만들어 저장함
-
4번의 가속도 값에 대해 한번 더 평균 값을 산출하여 평균 값에 대한 범위를 지정함
-
5번의 범위안에 도달하면 정지라 판단하고 챕처 이벤트를 시작함
-
만약 6번 과정에 도달하지 못했다면 4번에서 5번의 과정을 반복함
-
6번 정지 이벤트 시 2번 클라이언트에 정지 이벤트를 서버에 송신함
-
8번 후 정지 가속도 정보를 같은 디렉토리에 "stop.txt" 파일을 만들어 저장함
- 구동 영상
구동 환경
PC
CPU: Intel I7-10700K
RAM: 16GB
GPU: NVIDIA RTX 3080
LAN: 500MbpsRaspberry Pi 4
RAM: 8GB
WIFI: 5GHz
USB PORT: USB Camera
SENSOR: MPU-9250
- PC
클라이언트 연결 측
ip = 'ip 주소' # ip 주소
port = 3333 # port 번호
server_soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_soc.bind((ip, port))
server_soc.listen()
print("클라이언트 연결 대기")
c_soc, addr = server_soc.accept()
print(addr) #1번 클라이언트 연결
s_soc, addr2 = server_soc.accept()
print(addr2) #2번 클라이언트 연결
print("클라이언트 연결 성공")
실시간 영상 수신 측
data = b"" # 수신한 데이터를 넣을 변수
payload_size = struct.calcsize(">L")
while True:
# 프레임 수신
while len(data) < payload_size:
data += c_soc.recv(1024)
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack(">L", packed_msg_size)[0]
while len(data) < msg_size:
data += c_soc.recv(1024)
frame_data = data[:msg_size]
data = data[msg_size:]
frame = pickle.loads(frame_data, fix_imports=True,encoding="bytes")
# 직렬화되어 있는 binary file로 부터 객체로 역직렬화
frame = cv2.imdecode(frame, cv2.IMREAD_COLOR) # 프레임 디코딩
frame = cv2.resize(frame, None, fx=0.4, fy=0.4)
정지 이벤트 수신 측
with open("figure.names", "r") as f:
classes = [line.strip() for line in f.readlines()]
layer_names = net.getLayerNames()
output_layers = [layer_names[i - 1] for i in net.getUnconnectedOutLayers()]
***
cf=copy.deepcopy(frame)
msg1 = s_soc.recv(1024)
id2 = msg1.decode()
print(id2)
if id2 == '움직임':
cnt = 1
if cnt == 1 and id2 == '정지':
height, width, channels = cf.shape
blob = cv2.dnn.blobFromImage(cf, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
net.setInput(blob)
outs = net.forward(output_layers)
class_ids = []
confidences = []
boxes = []
for out in outs:
for detection in out:
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
if confidence > 0.85:
center_x = int(detection[0] * width)
center_y = int(detection[1] * height)
w = int(detection[2] * width)
h = int(detection[3] * height)
x = int(center_x - w / 2)
y = int(center_y - h / 2)
boxes.append([x, y, w, h])
confidences.append(float(confidence))
class_ids.append(class_id)
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
font = cv2.FONT_HERSHEY_PLAIN
for i in range(len(boxes)):
x, y, w, h = boxes[i]
label = str(classes[class_ids[i]])
color = (255, 0, 0)
cv2.rectangle(cf, (x, y), (x + w, y + h), color, 2)
cv2.putText(cf, label, (x, y + 30), font, 3, color, 3)
for i in range(len(boxes)):
xls['{col}{row}'.format(col=chr(ord('A')), row=(i + 2))] = str(classes[class_ids[i]])
for j in range(0, 4):
xls['{col}{row}'.format(col=chr(ord('B') + j), row=(i + 2))] = boxes[i][j]
cnt = 0
GUI 출력 측
class video(QObject):
sendImage = pyqtSignal(QImage)
sendImage2 = pyqtSignal(QImage)
def __init__(self, widget, size):
super().__init__()
self.widget = widget
self.size = size
self.sendImage.connect(self.widget.recvImage)
self.sendImage2.connect(self.widget.recvImage_2)
***
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = rgb.shape
bytesPerLine = ch * w
img = QImage(rgb.data, w, h, bytesPerLine, QImage.Format_RGB888)
resizedImg = img.scaled(self.size.width(), self.size.height(), Qt.KeepAspectRatio)
self.sendImage.emit(resizedImg)
rgb2 = cv2.cvtColor(cf, cv2.COLOR_BGR2RGB)
h, w, ch = rgb2.shape
bytesPerLine2 = ch * w
img2 = QImage(rgb2.data, w, h, bytesPerLine2, QImage.Format_RGB888)
resizedImg2 = img2.scaled(self.size.width(), self.size.height(), Qt.KeepAspectRatio)
self.sendImage2.emit(resizedImg2)
서버 꺼짐 버튼 클릭 시
def stopCam(self):
self.bThread = False
print("소켓 통신 종료")
***
if self.bThread == False:
wb.save('Detection_sheet.xlsx')
wb.close()
c_soc.close()
s_soc.close()
break