【问题标题】:Cut and save an object recognized by color剪切并保存通过颜色识别的对象
【发布时间】:2020-06-11 16:16:20
【问题描述】:

所以我想制作一个可以通过颜色、位置和清晰度检测物体的程序。 现在我可以通过颜色检测对象并绘制其轮廓和边界框。 我的问题是当程序识别出它的轮廓或边界框时,我真的不知道如何从图片中剪切出对象并将其保存为图片文件。

这是我的相机所看到的照片 input

output

我想将视频中绿色边界框内的内容剪掉 fps,只要您可以在视频中看到它。因此,如果视频为 30 fps,并且对象可见 10 秒,则需要拍摄 300 张照片。

代码如下:

我知道它看起来很糟糕,我只是想弄清楚用什么来让它工作

import cv2 as cv
import numpy as np
import os
import uuid

cap = cv.VideoCapture(1)
font = cv.FONT_HERSHEY_COMPLEX
path = os.getcwd()
print(path)


def createFolder(directory):
    try:
        if not os.path.exists(directory):
            os.makedirs(directory)
    except OSError:
        print('Error: Creating directory. ' + directory)


createFolder("./data")

# folderName = '%s' % (str(uuid.uuid4()))

while cap.isOpened():
    _, frame = cap.read()
    hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
    # blue is the chosen one for now
    lower_color = np.array([82, 33, 39])
    upper_color = np.array([135, 206, 194])
    mask = cv.inRange(hsv, lower_color, upper_color)

    kernel = np.ones((5, 5), np.uint8)
    mask = cv.erode(mask, kernel)

    contours, hierarchy = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    # find contour
    for contour in contours:
        area = cv.contourArea(contour)
        x, y, h, w = cv.boundingRect(contour)

        if area > 100:
            # bounding box
            # cv.rectangle(frame, (x - 40, y - 30), (x + h * 3, y + w * 3), (0, 255, 0), 1)
            # cutting and saving
            ext_left = tuple(contour[contour[:, :, 0].argmin()][0] - 20)
            ext_right = tuple(contour[contour[:, :, 0].argmax()][0] + 20)
            ext_top = tuple(contour[contour[:, :, 1].argmin()][0] - 20)
            ext_bot = tuple(contour[contour[:, :, 1].argmax()][0] + 20)

            outfile = '%s.jpg' % (str(uuid.uuid4()))
            cropped_image = frame[ext_top[1]:ext_bot[1], ext_left[0]:ext_right[0]]

            # write images to a specified folder
            cv.imwrite(os.path.join(path, "/data/", outfile), cropped_image)

    # outputs
    cv.imshow("Frame", frame)
    cv.imshow("Mask", mask)

    key = cv.waitKey(1)
    if key == 27:
        break

cap.release()
cv.destroyAllWindows()

【问题讨论】:

  • 嗨@Cerberus,保持伟大的工作,你非常接近!您缺少的是获取轮廓并创建蒙版,以便您只能从框架中复制对象像素。我发布了一个超越其他帖子和文档的答案。您还可以使用边界矩形进行裁剪,如this post 所示。让我知道这是否有效,我也可以编辑我的答案以帮助您。
  • 感谢您的帮助,我很感激。我是 python 的新手,这些链接和代码有很大帮助(节省大量时间)。如果我能实现它们,我会写。
  • @diogoslima 感谢您的帮助。现在我可以将对象写入磁盘。我的问题是我想将这些图像保存到当前工作目录中的指定文件夹中,但某些东西不能与“os.path.join”一起使用。所以我想将它们保存到/os.getcwd()/data/。我想我有语法错误。
  • 嗨@Cerberus,我对您的代码的快速阅读让我想知道这是否只是一个路径警告。你试过 -> cv.imwrite(os.path.join("./data/"), outfile),cropped_image)?

标签: python opencv


【解决方案1】:

专注于问题而忽略代码风格,我可以说你已经接近实现你的目标:)

要裁剪对象,您可以使用 Mat copyTo 方法。这是official OpenCV documentation,这是example from the OpenCV forums

现在,为了从轮廓创建蒙版,您可以使用已使用的相同 drawCountours 方法,但为厚度参数提供负值(例如,thickness=CV_FILLED)。您可以在stackoverflow post 中看到代码 sn-p,并在 official documentation 中查看详细信息。

要将图像保存到磁盘,您可以使用imwrite

因此,简而言之,将填充轮廓绘制到蒙版并使用该蒙版仅将对象像素从视频帧复制到另一个可以保存磁盘的垫子。

我将分享这个very similar question with an accepted answer,而不是发布代码,它可能包含您正在寻找的代码sn-p。

【讨论】:

    猜你喜欢
    • 2021-04-28
    • 2017-08-25
    • 2022-10-08
    • 1970-01-01
    • 2019-12-27
    • 2016-10-15
    • 2017-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多