首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >根据类类型将包围框坐标和图像保存到不同的文件夹中

根据类类型将包围框坐标和图像保存到不同的文件夹中
EN

Stack Overflow用户
提问于 2019-11-23 02:36:35
回答 1查看 9.7K关注 0票数 0

我使用OpenCV + Python来应用一个深入学习模型,并将对象分为8类(动物类型),即猫、狗、马、鹿、熊、蜥蜴、猴子,没有检测到对象(当图像中没有检测到对象时)。

我有一个文件夹,里面有各种动物的图片。我在一个文件夹中读取所有图像,然后应用深度学习模型提取每个图像中每个对象的边界框坐标。

我想首先通过将每一种动物图像放在相关的文件夹中来对每个图像进行分类。其次,将该图像的边界框的坐标保存在同一个文件夹中。例如,如果网络检测到cat,我希望将该图像和相应的坐标(作为文本文件.text)保存在cat文件夹中,如果它没有在图像中找到任何这些对象,只需将其放在无对象检测文件夹中。

我的问题是如何在8类文件夹中保存原始图像和该对象的边界框坐标?

这是我的代码:

代码语言:javascript
复制
import cv2
import numpy as np
import os
import glob
import argparse
import time

img_dir="/path/imgt/"
data_path=os.path.join(img_dir,'*g')
files=glob.glob(data_path)
data=[]

i = 0
for f1 in files:
     image=cv2.imread(f1)
     data.append(image)

     # construct the argument parse and parse the arguments
     ap = argparse.ArgumentParser()
     ap.add_argument("-i", "--image", required=True,
                     help="path to input image")
     ap.add_argument("-y", "--yolo", required=True,
                     help="base path to YOLO directory")
     ap.add_argument("-c", "--confidence", type=float, default=0.5,
                     help="minimum probability to filter weak detections")
     ap.add_argument("-t", "--threshold", type=float, default=0.3,
                     help="threshold when applyong non-maxima suppression")
     args = vars(ap.parse_args())

     # load the COCO class labels our YOLO model was trained on
     labelsPath = os.path.sep.join([args["yolo"], "obj.names"])
     LABELS = open(labelsPath).read().strip().split("\n")

     # initialize a list of colors to represent each possible class label
     np.random.seed(42)
     COLORS = np.random.randint(0, 255, size=(len(LABELS), 3),
                                dtype="uint8")

     # derive the paths to the YOLO weights and model configuration
     weightsPath = os.path.sep.join([args["yolo"], "yolo-obj_last.weights"])
     configPath = os.path.sep.join([args["yolo"], "yolo-obj.cfg"])

     # load our YOLO object detector trained on COCO dataset (80 classes)
     print("[INFO] loading YOLO from disk...")
     net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)

     # load our input image and grab its spatial dimensions
    # image = cv2.imread(args["image"])
     (H, W) = image.shape[:2]

     # determine only the *output* layer names that we need from YOLO
     ln = net.getLayerNames()
     ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]

     # construct a blob from the input image and then perform a forward
     # pass of the YOLO object detector, giving us our bounding boxes and
     # associated probabilities
     blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416),
                                  swapRB=True, crop=False)
     net.setInput(blob)
     start = time.time()
     layerOutputs = net.forward(ln)
     end = time.time()

     # show timing information on YOLO
     print("[INFO] YOLO took {:.6f} seconds".format(end - start))

     # initialize our lists of detected bounding boxes, confidences, and
     # class IDs, respectively
     boxes = []
     confidences = []
     classIDs = []

     # loop over each of the layer outputs
     for output in layerOutputs:
          # loop over each of the detections
          for detection in output:
               # extract the class ID and confidence (i.e., probability) of
               # the current object detection
               scores = detection[5:]
               classID = np.argmax(scores)
               confidence = scores[classID]

               # filter out weak predictions by ensuring the detected
               # probability is greater than the minimum probability
               if confidence > args["confidence"]:
                    # scale the bounding box coordinates back relative to the
                    # size of the image, keeping in mind that YOLO actually
                    # returns the center (x, y)-coordinates of the bounding
                    # box followed by the boxes' width and height
                    box = detection[0:4] * np.array([W, H, W, H])
                    (centerX, centerY, width, height) = box.astype("int")

                    # use the center (x, y)-coordinates to derive the top and
                    # and left corner of the bounding box
                    x = int(centerX - (width / 2))
                    y = int(centerY - (height / 2))

                    # update our list of bounding box coordinates, confidences,
                    # and class IDs
                    boxes.append([x, y, int(width), int(height)])
                    confidences.append(float(confidence))
                    classIDs.append(classID)

     # apply non-maxima suppression to suppress weak, overlapping bounding
     # boxes
     idxs = cv2.dnn.NMSBoxes(boxes, confidences, args["confidence"],
                             args["threshold"])

     # ensure at least one detection exists
     if len(idxs) > 0:
          # loop over the indexes we are keeping
          for i in idxs.flatten():
               # extract the bounding box coordinates
               (x, y) = (boxes[i][0], boxes[i][1])
               (w, h) = (boxes[i][2], boxes[i][3])

               # draw a bounding box rectangle and label on the image
               color = [int(c) for c in COLORS[classIDs[i]]]
               cv2.rectangle(image, (x, y), (x + w, y + h), color, 2)
               text = "{}: {:.4f}".format(LABELS[classIDs[i]], confidences[i])
               cv2.putText(image, text, (x, y - 7), cv2.FONT_HERSHEY_SIMPLEX,0.6, color, 2)
               path = '/path/imgr/' + LABELS[classIDs[i]] + '/'
               cv2.imwrite(os.path.join(path, 'image' + str(i) + '.jpg'), image)
               with open(os.path.join(path, 'image' + str(i) + '.txt'), 'a+') as f:
                 f.write(str(classIDs[i]) + ' ' + str(x) + ' ' + str(y) + ' ' + str(w) + ' ' + str(h))

文本文件看起来如何?

.txt -file为每个.jpg--图像--文件--位于同一个目录和同名,但使用.txt-extension,并放入该图像上的文件:对象号和对象坐标,对于新行中的每一个对象:<object-class> <x> <y> <width> <height>,其中:<object-class> --从0(classes-1) <x> <y> <width> <height>的对象整数--浮动值相对于图像的宽度和高度,它可以与(0.0 to 1.0]相同,例如:<x> = <absolute_x> / <image_width> or <height> = <absolute_height> / <image_height> atention:<x> <y> -是矩形的中心(不是左上角),例如,对于img1.jpg,您将创建包含:

代码语言:javascript
复制
1 0.716797 0.395833 0.216406 0.147222
0 0.687109 0.379167 0.255469 0.158333
1 0.420312 0.395833 0.140625 0.166667
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-11-23 04:36:45

也许是这样的:

代码语言:javascript
复制
 path = os.path.join('/path/imgr/', LABELS[classID], image_name)
 cv2.imwrite(path + '.jpg', image)
 with open(path + '.txt'), 'a+') as f:
    f.write(str(classID) + ' ' + str(detection[0]) + ' ' + str(detection[1]) + ' ' + str(detection[2]) + ' ' + str(detection[3]) + '\n')

图像中可能有多个对象,在这种情况下,图像应该写入每个相关文件夹,如果存在文本文件,则应附加到文本文件中。

image_name将是您生成的东西,您可以使用您正在读取的名称或计数器。

这个片段应该放在if语句下面的某个地方:

代码语言:javascript
复制
if confidence > args["confidence"]: 

我会把它放在最后。你可能需要做一些小的调整,但这才是重点。

更明确地:

代码语言:javascript
复制
import cv2
import numpy as np
import os
import glob
import argparse
import time

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
#ap.add_argument("-i", "--image", required=True,
#                help="path to input image")
ap.add_argument("-y", "--yolo", required=True,
                help="base path to YOLO directory")  
ap.add_argument("-c", "--confidence", type=float, default=0.5,
                help="minimum probability to filter weak detections")
ap.add_argument("-t", "--threshold", type=float, default=0.3,
                help="threshold when applyong non-maxima suppression")
args = vars(ap.parse_args())

# load the COCO class labels our YOLO model was trained on
labelsPath = os.path.sep.join([args["yolo"], "obj.names"])
LABELS = open(labelsPath).read().strip().split("\n")

# derive the paths to the YOLO weights and model configuration
weightsPath = os.path.sep.join([args["yolo"], "yolo-obj_last.weights"])
configPath = os.path.sep.join([args["yolo"], "yolo-obj.cfg"])

# load our YOLO object detector trained on COCO dataset (80 classes)
print("[INFO] loading YOLO from disk...")
net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)

# determine only the *output* layer names that we need from YOLO
ln = net.getLayerNames()
ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]

img_dir="/path/imgt/"
data_path=os.path.join(img_dir,'*g')
files=glob.glob(data_path)

for f1 in files:
    # load our input image and grab its spatial dimensions
    image=cv2.imread(f1)

    # construct a blob from the input image and then perform a forward
    # pass of the YOLO object detector, giving us our bounding boxes and
    # associated probabilities
    blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416),
                                 swapRB=True, crop=False)
    net.setInput(blob)
    layerOutputs = net.forward(ln)

    # loop over each of the layer outputs
    for output in layerOutputs:
         # loop over each of the detections
         for detection in output:
              # extract the class ID and confidence (i.e., probability) of
              # the current object detection
              scores = detection[5:]
              classID = np.argmax(scores)
              confidence = scores[classID]
              box = detection[0:4]
              # get upper left corner
              box[0] = box[0] - box[2]/2
              box[1] = box[1] - box[3]/2

              # filter out weak predictions by ensuring the detected
              # probability is greater than the minimum probability
              if confidence > args["confidence"]:
                  # write output files
                  class_dir = os.path.join('/path/imgr/', LABELS[classID])
                  if not os.path.exists(class_dir):
                      os.makedirs(class_dir)
                  path = os.path.join(class_dir, f1.split('/')[-1][:-4])
                  cv2.imwrite(path + '.jpg', image)
                  with open(path + '.txt'), 'a+') as f:
                      f.write(str(classID) + ' ' + str(box[0]) + ' ' + str(box[1]) + ' ' + str(box[2]) + ' ' + str(box[3]) + '\n')

仔细阅读,确保您理解for循环中的每个部分都在做什么。一旦您满意这个最小的例子,您可以添加回非最大抑制和绘制包围框,如果您愿意。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59004046

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档