| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| import os.path |
| import cv2 as cv |
| import argparse |
| import sys |
| import numpy as np |
| import json |
| from PIL import ImageFont, ImageDraw, Image |
|
|
| from config import config |
|
|
| parser = argparse.ArgumentParser(description='Food Classification and Localization ver. 0.9') |
| parser.add_argument('--image', help='Full path to image file.') |
| parser.add_argument('--video', help='Full path to video file.') |
| parser.add_argument('--showText', type=int, default=1, help='show text in the output.') |
| parser.add_argument('--ps', type=int, default=1, help='stop each image in the screen.') |
| args = parser.parse_args() |
|
|
| |
| args.image = config.TEST_IMAGE_PATH |
| args.video = config.TEST_VIDEO_PATH |
| args.showText = config.SHOW_TEXT_FLAG |
| args.ps = config.PS_FLAG |
|
|
| |
| confThreshold = config.CONF_THRES |
| nmsThreshold = config.NMS_THRES |
|
|
| |
| inpWidth = config.INPWIDTH |
| inpHeight = config.INPHEIGHT |
|
|
| |
| modelBaseDir = config.ModelBaseDir |
|
|
| |
| classesFile = os.path.sep.join([modelBaseDir, config.CLASSES_FILE]) |
| classes = None |
| with open(classesFile, 'rt', encoding='utf-8') as f: |
| classes = f.read().rstrip('\n').split('\n') |
|
|
| |
| classes_File_Codes = os.path.sep.join([modelBaseDir, config.CLASSES_FILE_CODE]) |
| classes_codes = None |
| with open(classes_File_Codes, 'rt', encoding='utf-8') as f: |
| classes_codes = f.read().rstrip('\n').split('\n') |
|
|
| assert (len(classes) == len(classes_codes)) |
|
|
| |
| modelConfiguration = os.path.sep.join([modelBaseDir, config.Model_Configuration]) |
| modelWeights = os.path.sep.join([modelBaseDir, config.Model_Weights]) |
|
|
| |
| net = cv.dnn.readNetFromDarknet(modelConfiguration, modelWeights) |
| net.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV) |
| net.setPreferableTarget(cv.dnn.DNN_TARGET_OPENCL_FP16) |
|
|
| |
| def getOutputsNames(net): |
| |
| layersNames = net.getLayerNames() |
| |
| |
| unconnected = net.getUnconnectedOutLayers() |
| if len(unconnected.shape) == 1: |
| return [layersNames[i - 1] for i in unconnected] |
| else: |
| return [layersNames[i[0] - 1] for i in unconnected] |
|
|
| |
| def drawPred(frame, classId, conf, left, top, right, bottom): |
| |
| |
| cv.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 3) |
|
|
| label = '%.2f' % conf |
|
|
| |
| if classes: |
| assert (classId < len(classes)) |
| |
| label = u'%s' % (classes[classId]) |
| |
| print('label:{}, class_id:{}'.format(label, classId)) |
|
|
|
|
| |
| labelSize, baseLine = cv.getTextSize(label, cv.FONT_HERSHEY_SIMPLEX, 0.5, 1) |
| top = max(top, labelSize[1]) |
| if args.showText: |
| |
| |
| cv.rectangle(frame, (left, top - round(1.5*labelSize[1])), (left + round(1.5*labelSize[0]), top + baseLine), (0, 255, 255), cv.FILLED) |
| cv.putText(frame, label, (left, top), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 0), 2) |
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| def postprocess(frame, outs, showimg=False): |
| frameHeight = frame.shape[0] |
| frameWidth = frame.shape[1] |
|
|
| |
| |
| classIds = [] |
| confidences = [] |
| boxes = [] |
| for out in outs: |
| if(args.showText): |
| print("out.shape : ", out.shape) |
| for detection in out: |
| |
| scores = detection[5:] |
| classId = np.argmax(scores) |
| |
| confidence = scores[classId] |
| if detection[4] >= confThreshold: |
| if(args.showText): |
| print('obj score: ', detection[4], " - confidence:", scores[classId], " - thres : ", confThreshold) |
| |
| if confidence >= confThreshold: |
| center_x = int(detection[0] * frameWidth) |
| center_y = int(detection[1] * frameHeight) |
| width = int(detection[2] * frameWidth) |
| height = int(detection[3] * frameHeight) |
| left = int(center_x - width / 2) |
| top = int(center_y - height / 2) |
| classIds.append(classId) |
| confidences.append(float(confidence)) |
| boxes.append([left, top, width, height]) |
| |
| |
| |
|
|
| |
| |
| indices = cv.dnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold) |
| rests =[] |
| for i in indices: |
| |
| idx = i[0] if isinstance(i, (list, tuple, np.ndarray)) and len(i) > 0 else i |
| box = boxes[idx] |
| left = box[0] |
| top = box[1] |
| width = box[2] |
| height = box[3] |
| rests.append([classIds[idx], left, top, width, height, frameWidth, frameHeight]) |
| if(showimg): |
| drawPred(frame, classIds[idx], confidences[idx], left, top, left + width, top + height) |
|
|
| return rests |
|
|
| def food_classifier_Json(image): |
| |
| print(args.showText) |
| locations = food_classifier_pipeline(frame=image) |
| jsons = [] |
| for j,location in enumerate(locations): |
| class_id, x, y, width, height, framewidth, frameheight =location |
| res_json = {} |
| res_json["ClassID"] = classes_codes[class_id] |
| res_json["ClassName"] = classes[class_id] |
| res_json["x"] = int(x) |
| res_json["y"] = int(y) |
| res_json["w"] = int(width) |
| res_json["h"] = int(height) |
| res_json["framewidth"] = int(framewidth) |
| res_json["frameheight"]= int(frameheight) |
| jsons.append(res_json) |
| print(json.dumps(jsons,ensure_ascii=False)) |
|
|
| return json.dumps(jsons,ensure_ascii=False) |
|
|
| def food_classifier_pipeline(frame): |
|
|
| |
| blob = cv.dnn.blobFromImage(frame, 1 / 255, (inpWidth, inpHeight), [0, 0, 0], 1, crop=False) |
| |
| net.setInput(blob) |
| |
| outs = net.forward(getOutputsNames(net)) |
| final_infos = postprocess(frame, outs) |
|
|
| return final_infos |
|
|
| |
| def main(main_args): |
| winName = 'Food Classification Results' |
| |
| m_startFrame = np.maximum(0, config.Video_Start_Frame) |
|
|
| outputFile = "yolo_out_py.avi" |
| if (main_args.image): |
| |
| if not os.path.isfile(main_args.image): |
| print("Input image file ", main_args.image, " doesn't exist") |
| sys.exit(1) |
| cap = cv.VideoCapture(main_args.image) |
| outputFile = args.image[:-4] + '_yolo_out_py.jpg' |
| elif (main_args.video): |
| |
| if not os.path.isfile(main_args.video): |
| print("Input video file ", main_args.video, " doesn't exist") |
| sys.exit(1) |
| cap = cv.VideoCapture(main_args.video) |
| cap.set(cv.CAP_PROP_POS_FRAMES, m_startFrame) |
| outputFile = main_args.video[:-4] + '_yolo_out_py.avi' |
| else: |
| |
| cap = cv.VideoCapture(0) |
|
|
| |
| if (not main_args.image): |
| vid_writer = cv.VideoWriter(outputFile, cv.VideoWriter_fourcc('M', 'J', 'P', 'G'), 30, |
| (round(cap.get(cv.CAP_PROP_FRAME_WIDTH)), round(cap.get(cv.CAP_PROP_FRAME_HEIGHT)))) |
| pcontinue = True |
| while pcontinue: |
|
|
| |
| hasFrame, frame = cap.read() |
|
|
| |
| if not hasFrame: |
| print("Done processing !!!") |
| print("Output file is stored as ", outputFile) |
| |
| |
| |
| |
|
|
| |
|
|
| |
| blob = cv.dnn.blobFromImage(frame, 1 / 255, (inpWidth, inpHeight), [0, 0, 0], 1, crop=False) |
| |
| net.setInput(blob) |
| |
| outs = net.forward(getOutputsNames(net)) |
| if main_args.showText: |
| print(getOutputsNames(net)) |
|
|
| postprocess(frame, outs, showimg=True) |
|
|
| |
| if main_args.showText: |
| t, _ = net.getPerfProfile() |
| label = 'Inference time: %.2f ms' % (t * 1000.0 / cv.getTickFrequency()) |
| print(label) |
| cv.putText(frame, label, (0, 15), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255)) |
|
|
| |
| if (main_args.image): |
| cv.imwrite(outputFile, frame.astype(np.uint8)); |
| else: |
| vid_writer.write(frame.astype(np.uint8)) |
|
|
| |
| |
| pcontinue=False |
|
|
| if __name__ == "__main__": |
| main(main_args=args) |
|
|