【问题标题】:cv2.imshow shows 9 screens instead of 1cv2.imshow 显示 9 个屏幕而不是 1 个
【发布时间】:2017-11-10 01:01:50
【问题描述】:

我正在构建一些代码来自适应地检测网络摄像头视频中的皮肤。我几乎可以正常工作,但是,在输出视频时,它显示了 9 个“皮肤”蒙版屏幕,而不仅仅是一个。好像我只是错过了一些简单的东西,但我无法弄清楚。

image shown here

代码如下:

# first let's train the data
data, labels = ReadData()
classifier = TrainTree(data, labels)

# get the webcam. The input is either a video file or the camera number
# since using laptop webcam (only 1 cam), input is 0. A 2nd cam would be input 1
camera = cv2.VideoCapture(0)

while True:
    # reads in the current frame
    # .read() returns True if frame read correctly, and False otherwise
    ret, frame = camera.read()   # frame.shape: (480,640,3)

    if ret:
        # reshape the frame to follow format of training data (rows*col, 3)
        data = np.reshape(frame, (frame.shape[0] * frame.shape[1], 3))
        bgr = np.reshape(data, (data.shape[0], 1, 3))
        hsv = cv2.cvtColor(np.uint8(bgr), cv2.COLOR_BGR2HSV)
        # once we have converted to HSV, we reshape back to original shape of (245057,3)
        data = np.reshape(hsv, (hsv.shape[0], 3))
        predictedLabels = classifier.predict(data)

        # the AND operator applies the skinMask to the image
        # predictedLabels consists of 1 (skin) and 2 (non-skin), needs to change to 0 (non-skin) and 255 (skin)
        predictedMask = (-(predictedLabels - 1) + 1) * 255   # predictedMask.shape: (307200,)

        # resize to match frame shape
        imgLabels = np.resize(predictedMask, (frame.shape[0], frame.shape[1], 3))   # imgLabels.shape: (480,640,3)
        # masks require 1 channel, not 3, so change from BGR to GRAYSCALE
        imgLabels = cv2.cvtColor(np.uint8(imgLabels), cv2.COLOR_BGR2GRAY)   # imgLabels.shape: (480,640)

        # do bitwsie AND to pull out skin pixels. All skin pixels are anded with 255 and all others are 0
        skin = cv2.bitwise_and(frame, frame, mask=imgLabels) # skin.shape: (480,640,3)
        # show the skin in the image along with the mask, show images side-by-side
        # **********THE BELOW LINE OUTPUTS 9 screens of the skin mask instead of just 1  ****************
        cv2.imshow("images", np.hstack([frame, skin]))

        # if the 'q' key is pressed, stop the loop
        if cv2.waitKey(1) & 0xFF == ord("q"):
            break
    else:
        break

# release the video capture
camera.release()
cv2.destroyAllWindows()

【问题讨论】:

  • 为什么不打印结果的形状?
  • 我编辑了我的代码以添加每个变量的形状(见上文)。 predictMask 为 307200(即 rows*cols),resize 后的 imgLabels 大于 307200,变为 (480,640,3)。也许这是导致错误的原因?但是,将imgLabels输入到cvtColor BGR到GRAY需要3的颜色通道。我尝试将调整大小更改为将 imgLabels 输出为 (480,640,1),然后注释掉转换为 GRAY,但最终出现此错误:“error: (-215) (mtype == CV_8U || mtype == CV_8S ) && _mask.sameSize(*psrc1) in function cv::binary_op" 任何帮助表示赞赏!
  • 我不知道给分类器喂什么。但我认为您转换颜色的方法是错误的。而且程序不完整,无法调试。

标签: python python-3.x opencv


【解决方案1】:

您正在使用位图。要了解他们持有什么,请单独cv2.imshow他们。然后你会看到(字面上)数据出错的地方。


现在,罪魁祸首很可能是np.resize()

np.resize(a, new_shape)

返回一个具有指定形状的新数组。

如果新数组大于原数组,那么新数组 充满了a的重复副本。请注意,此行为是 不同于 a.resize(new_shape) 填充零而不是 a 的重复副本。


缩放位图(=在努力保留相同视觉图像的同时调整大小),请按照OpenCV: Geometric Transformations of Images 使用cv2.resize()

【讨论】:

  • 我明白了,但是,我需要调整大小以将 predictMask 整形为一个数组,但 cvtColor 转换为灰度时除外。我不确定如何更改调整大小行来解决此问题。
  • @Rachel 你读过最后一段吗?也许配方不清楚。
  • 啊,我明白了,我看错了最后一部分。所以我的下一个问题是 cv2.resize 可以将一维数组调整为二维数组,给我一个 (rows, cols) 数组。但是,对于将 cvtColor 转换为灰度,我需要添加颜色通道以获取 (rows, cols, 3),并且我没有看到使用 cv2.resize 执行此操作的方法...
  • @Rachel 我你有一个由 255 和 0 组成的 (307200,) 数组(实际上,灰度位图拉伸成一条线(我猜)),你可以将 np.reshape 它变成正常形状(640,480)。这样,它已经是一个很好的灰度位图——无需将其转换为(640,480,3) 然后再返回。灰度位图只有一个通道。
  • 我终于能够解决这个问题。我认为我的 imgLabels 数组没有被正确地排除为图像数组。所以我将二进制数组作为图像写入磁盘,然后将图像作为新数组重新打开。然后将这个新变量作为掩码传入。这最终奏效了。很高兴它正在工作,但似乎仍然像一个hack-around。也许一旦我了解更多,我会找到更好的解决方案。不过感谢您的所有帮助!
猜你喜欢
  • 1970-01-01
  • 2020-01-16
  • 1970-01-01
  • 2018-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-24
相关资源
最近更新 更多