为什么一些目标检测神经网络在OpenCV 4.1.0中返回全零?

30
我在使用Java/Scala中的OpenCV 4.1.0评估多个神经网络时遇到问题。对于fish-bike图像以及其他图像,网络返回全零。我在以下网络中观察到了这一现象:

使用YOLOv3-spp和YOLOv3-tiny进行检测正常https://pjreddie.com/darknet/yolo/

这个dnn究竟有什么问题呢?

// The reproduce in Scala REPL you need a hack:

def loadLibraryScalaREPL(libraryName: String): Unit = {
  val loadLibrary0 = Runtime.getRuntime.getClass.getDeclaredMethods()(4)
  loadLibrary0.setAccessible(true)
  loadLibrary0.invoke(Runtime.getRuntime, scala.tools.nsc.interpreter.IMain.getClass, libraryName)
}

loadLibraryScalaREPL(org.opencv.core.Core.NATIVE_LIBRARY_NAME)

// To load in Java/Scala application just use System.loadLibrary.

import org.opencv.core.{Scalar, Size}
import org.opencv.dnn.Dnn
import org.opencv.imgcodecs.Imgcodecs
    
val image = Imgcodecs.imread("/root/fish-bike.jpg")
val net = Dnn.readNetFromCaffe("/tmp/VGG_coco_SSD_512x512_iter_360000.prototxt", "/tmp/VGG_coco_SSD_512x512_iter_360000.caffemodel")
val blob = Dnn.blobFromImage(image, 1/125.0, new Size(512, 512), new Scalar(104,117,123), true)
net.setInput(blob)
val layer = net.forward()
val values = new Array[Float](layer.total().toInt)
layer.get(0,0, values)
values.grouped(7).foreach(x => println(x.toList))

2
你为什么在 val values = new Array[Float](layer.total().toInt) 中使用 toInt?这不会首先将你的值转换为整数(并有效地将所有值四舍五入为零),然后再转换回浮点数(保持它们为0.0)吗? - Anton Codes
你好 @AntonCodes。我明白这个想法。不,这是数组的大小。 - Vladimir Protsenko
你能否更新你的问题,展示来自fish-bike.jpg的数值,如果可能的话,再展示一个使用相同神经网络返回你所期望结果的其他图像的数值。 - Anton Codes
一个天真的评论:这是否与opencv读取BGR图像而其他软件读取RGB有关? - colt.exe
1个回答

1
一些模型期望通道强度的归一化值。通常,图像用uint8像素表示(取值范围从0 ~ 255)。您需要将其转换为float32(从-1 ~ 1)。基本上,对于这样的模型,您的图像将被解释为一张空白图片(大部分是所有白色像素)。
以下是一个可以用来归一化图像的Python函数:
def processFrame(image):
    img = cv2.resize(image, (input_width, input_height)) # input sizes of detector 
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    # Normalize pixel values if using a floating model
    img_rgb = (np.float32(img_rgb) - 127.5) / 127.5

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接