如何使用Python将OpenCV检测数据追加写入CSV并解决格式错误问题
问题原因
你的代码主要存在4个错误导致输出不符合预期:
csv.writer的writerow()方法要求传入元素为每个字段值的列表,如果传入拼接好的字符串,会把每个字符单独作为一个字段写入,逗号也会被自动转义加引号,就是你看到的错误输出- 写入时用了未定义的变量
data_pixel,前面组装数据的变量名是data,变量名不匹配 - 写入CSV的代码放在了遍历图片的for循环外部,只会执行一次,没法每行存一张图片的结果
w/h/ew/eh都是在人脸、眼睛检测的for循环内部定义的,如果某张图没检测到人脸/眼睛,会直接报变量未定义的错误,需要加边界判断
修改方案
前面的视频采集代码保持不变,只需要修改后面遍历图片+写入CSV的部分即可,修改后完整代码段如下:
import cv2 import os import time import pandas as pd import numpy as np import matplotlib.pyplot as plt from csv import writer faceCascade = cv2.CascadeClassifier( cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') eyeCascade = cv2.CascadeClassifier( cv2.data.haarcascades + 'haarcascade_eye.xml') font = cv2.FONT_HERSHEY_SIMPLEX sampel_foto = 5 counter = 1 jarak = 50 dir_name = 'C:/MyDrive' video_capture = cv2.VideoCapture(1) while True: # Capture frame-by-frame ret, frame = video_capture.read() frame_copy = frame.copy() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale( gray, scaleFactor=1.2, flags=cv2.CASCADE_SCALE_IMAGE) # Draw a rectangle around the faces for (x, y, w, h) in faces: cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 3) roi_gray = gray[y:y+h, x:x+w] roi_color = frame[y:y+h, x:x+w] cv2.putText(frame, 'face: '+str(w)+','+str(h), (10, 30), font, 0.6, (255, 255, 255), 2) eyes = eyeCascade.detectMultiScale(roi_gray) # Draw a rectangle around the eyes for (ex, ey, ew, eh) in eyes: cv2.rectangle(roi_color, (ex, ey), (ex+ew, ey+eh), (0, 255, 0), 2) cv2.putText(frame, 'eyes: '+str(ew)+','+str(eh), (10, 50), font, 0.6, (255, 255, 255), 2) if cv2.waitKey(1) & 0xFF == ord('c'): cv2.imwrite(f'{dir_name}{jarak}.{counter}.jpg', frame_copy) print(f'simpan foto ke-{counter} dengan jarak: {jarak} cm!') counter += 1 if counter > sampel_foto: break # Display the resulting frame cv2.imshow('Video', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break # When everything is done, release the capture video_capture.release() cv2.destroyAllWindows() # Get list of all files only in the given directory imfilelist = [os.path.join(dir_name, f) for f in os.listdir(dir_name) if f.endswith(".jpg")] # Sort list of files based on last modification time in ascending order list_of_files = sorted( imfilelist, key=lambda x: os.path.getmtime(os.path.join(dir_name, x))) # 先打开CSV文件,避免每次循环重复打开关闭,加newline=''避免Windows下输出空行 with open('test.csv', 'a', newline='') as f_object: writer_object = writer(f_object) # 遍历每张图片 for el in list_of_files: imagen = cv2.imread(el) gray = cv2.cvtColor(imagen, cv2.COLOR_BGR2GRAY) # 初始化变量,避免未定义错误 w = h = ew = eh = 0 roi_gray = None # Detect faces faces = faceCascade.detectMultiScale( gray, scaleFactor=1.2, flags=cv2.CASCADE_SCALE_IMAGE) if len(faces) > 0: x, y, w, h = faces[0] # 取检测到的第一张人脸 cv2.rectangle(imagen, (x, y), (x + w, y + h), (0, 255, 0), 2) roi_gray = gray[y:y+h, x:x+w] roi_color = imagen[y:y+h, x:x+w] # Detect eyes eyes = eyeCascade.detectMultiScale(roi_gray) if len(eyes) > 0: ex, ey, ew, eh = eyes[0] cv2.rectangle(roi_color, (ex, ey), (ex+ew, ey+eh), (0, 255, 0), 2) # 组装列表,直接传数值即可不需要转字符串 data_row = [w, h, ew, eh, jarak] print(','.join([str(i) for i in data_row])) # 仅写入有效检测结果,不需要可以删掉这个判断 if w > 0 and ew > 0: writer_object.writerow(data_row)
补充说明
如果需要保留表头,可以在打开CSV后先判断文件是否为空,为空的话先写入表头行['face_width', 'face_height', 'eye_width', 'eye_height', 'distance']即可。
内容的提问来源于stack exchange,提问作者Dev Dexvils
相关产品推荐
相关产品推荐

