Files
gocv/dnn_test.go

528 lines
13 KiB
Go

//go:build !gocv_specific_modules || (gocv_specific_modules && gocv_dnn)
package gocv
import (
"image"
"os"
"path/filepath"
"testing"
)
func TestReadNetDiskFromTensorflow(t *testing.T) {
path := os.Getenv("GOCV_TENSORFLOW_TEST_FILES")
if path == "" {
t.Skip("Unable to locate Tensorflow model files for tests")
}
net := ReadNet(path+"/tensorflow_inception_graph.pb", "")
if net.Empty() {
t.Errorf("Unable to load Tensorflow model using ReadNet")
}
defer net.Close()
checkTensorflowNet(t, net)
}
func TestReadNetMemoryFromTensorflow(t *testing.T) {
path := os.Getenv("GOCV_TENSORFLOW_TEST_FILES")
if path == "" {
t.Skip("Unable to locate Tensorflow model files for tests")
}
bModel, err := os.ReadFile(path + "/tensorflow_inception_graph.pb")
if err != nil {
t.Errorf("Failed to load model from file: %v", err)
}
_, err = ReadNetBytes("tensorflow", nil, nil)
if err == nil {
t.Errorf("Should have error for reading nil model bytes")
}
net, err := ReadNetBytes("tensorflow", bModel, nil)
if err != nil {
t.Errorf("Failed to read net bytes: %v", err)
}
if net.Empty() {
t.Errorf("Unable to load Tensorflow model using ReadNetBytes")
}
defer net.Close()
checkTensorflowNet(t, net)
}
func TestReadNetDiskFromONNX(t *testing.T) {
path := os.Getenv("GOCV_ONNX_TEST_FILES")
if path == "" {
t.Skip("Unable to locate ONNX model files for tests")
}
net := ReadNet(filepath.Join(path, "googlenet-9.onnx"), "")
if net.Empty() {
t.Errorf("Unable to load ONNX model using ReadNet")
}
defer net.Close()
checkONNXNet(t, net)
}
func TestReadNetMemoryFromONNX(t *testing.T) {
path := os.Getenv("GOCV_ONNX_TEST_FILES")
if path == "" {
t.Skip("Unable to locate ONNX model files for tests")
}
bModel, err := os.ReadFile(filepath.Join(path, "googlenet-9.onnx"))
if err != nil {
t.Errorf("Failed to load model from file: %v", err)
}
_, err = ReadNetBytes("onnx", nil, nil)
if err == nil {
t.Errorf("Should have error for reading nil model bytes")
}
net, err := ReadNetBytes("onnx", bModel, nil)
if err != nil {
t.Errorf("Failed to read net bytes: %v", err)
}
if net.Empty() {
t.Errorf("Unable to load Caffe model using ReadNetBytes")
}
defer net.Close()
checkONNXNet(t, net)
}
func checkTensorflowNet(t *testing.T, net Net) {
img := IMRead("images/space_shuttle.jpg", IMReadColor)
if img.Empty() {
t.Error("Invalid Mat in Tensorflow test")
}
defer img.Close()
blob := BlobFromImage(img, 1.0, image.Pt(224, 224), NewScalar(0, 0, 0, 0), true, false)
if blob.Empty() {
t.Error("Invalid blob in Tensorflow test")
}
defer blob.Close()
net.SetInput(blob, "input")
prob := net.Forward("softmax2")
defer prob.Close()
if prob.Empty() {
t.Error("Invalid softmax2 in Tensorflow test")
}
probMat := prob.Reshape(1, 1)
defer probMat.Close()
_, maxVal, minLoc, maxLoc := MinMaxLoc(probMat)
if round(float64(maxVal), 0.00005) != 1.0 {
t.Errorf("Tensorflow maxVal incorrect: %v\n", round(float64(maxVal), 0.00005))
}
if minLoc.X != 481 || minLoc.Y != 0 {
t.Errorf("Tensorflow minLoc incorrect: %v\n", minLoc)
}
if maxLoc.X != 234 || maxLoc.Y != 0 {
t.Errorf("Tensorflow maxLoc incorrect: %v\n", maxLoc)
}
}
func TestTensorflowDisk(t *testing.T) {
path := os.Getenv("GOCV_TENSORFLOW_TEST_FILES")
if path == "" {
t.Skip("Unable to locate Tensorflow model file for tests")
}
net := ReadNetFromTensorflow(path + "/tensorflow_inception_graph.pb")
if net.Empty() {
t.Errorf("Unable to load Tensorflow model")
}
defer net.Close()
checkTensorflowNet(t, net)
}
func TestTensorflowMemory(t *testing.T) {
path := os.Getenv("GOCV_TENSORFLOW_TEST_FILES")
if path == "" {
t.Skip("Unable to locate Tensorflow model file for tests")
}
b, err := os.ReadFile(path + "/tensorflow_inception_graph.pb")
if err != nil {
t.Errorf("Failed to load tensorflow model from file: %v", err)
}
net, err := ReadNetFromTensorflowBytes(b)
if err != nil {
t.Errorf("Failed to load Tensorflow model from bytes: %v", err)
}
if net.Empty() {
t.Errorf("Unable to load Tensorflow model")
}
defer net.Close()
checkTensorflowNet(t, net)
}
func TestOnnxMemory(t *testing.T) {
path := os.Getenv("GOCV_ONNX_TEST_FILES")
if path == "" {
t.Skip("Unable to locate ONNX model file for tests")
}
b, err := os.ReadFile(filepath.Join(path, "googlenet-9.onnx"))
if err != nil {
t.Errorf("Failed to load ONNX from file: %v", err)
}
net, err := ReadNetFromONNXBytes(b)
if err != nil {
t.Errorf("Failed to load Tensorflow model from bytes: %v", err)
}
if net.Empty() {
t.Errorf("Unable to load Tensorflow model")
}
defer net.Close()
checkONNXNet(t, net)
}
func TestOnnxDisk(t *testing.T) {
path := os.Getenv("GOCV_ONNX_TEST_FILES")
if path == "" {
t.Skip("Unable to locate ONNX model file for tests")
}
net := ReadNetFromONNX(filepath.Join(path, "googlenet-9.onnx"))
if net.Empty() {
t.Errorf("Unable to load ONNX model")
}
defer net.Close()
checkONNXNet(t, net)
}
func checkONNXNet(t *testing.T, net Net) {
img := IMRead("images/space_shuttle.jpg", IMReadColor)
if img.Empty() {
t.Error("Invalid Mat in ONNX test")
}
defer img.Close()
blob := BlobFromImage(img, 1.0, image.Pt(224, 224), NewScalar(0, 0, 0, 0), true, false)
if blob.Empty() {
t.Error("Invalid blob in ONNX test")
}
defer blob.Close()
net.SetInput(blob, "data_0")
prob := net.Forward("prob_1")
defer prob.Close()
if prob.Empty() {
t.Error("Invalid output in ONNX test")
}
probMat := prob.Reshape(1, 1)
defer probMat.Close()
_, maxVal, minLoc, maxLoc := MinMaxLoc(probMat)
if round(float64(maxVal), 0.0005) != 0.9965 {
t.Errorf("ONNX maxVal incorrect: %v\n", round(float64(maxVal), 0.0005))
}
if minLoc.X != 955 || minLoc.Y != 0 {
t.Errorf("ONNX minLoc incorrect: %v\n", minLoc)
}
if maxLoc.X != 812 || maxLoc.Y != 0 {
t.Errorf("ONNX maxLoc incorrect: %v\n", maxLoc)
}
}
func TestBlobFromImages(t *testing.T) {
imgs := make([]Mat, 0)
img := IMRead("images/space_shuttle.jpg", IMReadColor)
if img.Empty() {
t.Error("Invalid Mat in BlobFromImages test")
}
defer img.Close()
imgs = append(imgs, img)
imgs = append(imgs, img)
blob := NewMat()
BlobFromImages(imgs, &blob, 1.0, image.Pt(25, 25), NewScalar(0, 0, 0, 0), false, false, MatTypeCV32F)
defer blob.Close()
sz := GetBlobSize(blob)
if sz.Val1 != 2 || sz.Val2 != 3 || sz.Val3 != 25 || sz.Val4 != 25 {
t.Errorf("GetBlobSize in BlobFromImages retrieved wrong values")
}
}
func TestBlobFromImageGreyscale(t *testing.T) {
img := IMRead("images/space_shuttle.jpg", IMReadGrayScale)
if img.Empty() {
t.Error("Invalid Mat in TestBlobFromImageGreyscale test")
}
defer img.Close()
blob := BlobFromImage(img, 1.0, image.Pt(100, 100), NewScalar(0, 0, 0, 0), false, false)
defer blob.Close()
if blob.Empty() {
t.Errorf("BlobFromImageGreyscale failed to create blob")
}
}
func TestBlobFromImageWithParams(t *testing.T) {
img := IMRead("images/space_shuttle.jpg", IMReadColor)
if img.Empty() {
t.Error("Invalid Mat in BlobFromImages test")
}
defer img.Close()
params := NewImageToBlobParams(1.0, image.Pt(25, 25), NewScalar(0, 0, 0, 0), false, MatTypeCV32F, DataLayoutNCHW, PaddingModeCropCenter, NewScalar(0, 0, 0, 0))
blob := BlobFromImageWithParams(img, params)
defer blob.Close()
sz := GetBlobSize(blob)
if sz.Val1 != 1 || sz.Val2 != 3 || sz.Val3 != 25 || sz.Val4 != 25 {
t.Errorf("GetBlobSize in BlobFromImagesWithParams retrieved wrong values: %v\n", sz)
}
}
func TestBlobFromImagesWithParams(t *testing.T) {
imgs := make([]Mat, 0)
img := IMRead("images/space_shuttle.jpg", IMReadColor)
if img.Empty() {
t.Error("Invalid Mat in BlobFromImagesWithParams test")
}
defer img.Close()
imgs = append(imgs, img)
imgs = append(imgs, img)
params := NewImageToBlobParams(1.0, image.Pt(25, 25), NewScalar(0, 0, 0, 0), false, MatTypeCV32F, DataLayoutNCHW, PaddingModeCropCenter, NewScalar(0, 0, 0, 0))
blob := NewMat()
BlobFromImagesWithParams(imgs, &blob, params)
defer blob.Close()
sz := GetBlobSize(blob)
if sz.Val1 != 2 || sz.Val2 != 3 || sz.Val3 != 25 || sz.Val4 != 25 {
t.Errorf("GetBlobSize in BlobFromImagesWithParams retrieved wrong values: %v\n", sz)
}
}
func TestImagesFromBlob(t *testing.T) {
imgs := make([]Mat, 0)
img := IMRead("images/space_shuttle.jpg", IMReadGrayScale)
if img.Empty() {
t.Error("Invalid Mat in BlobFromImages test")
}
defer img.Close()
imgs = append(imgs, img)
imgs = append(imgs, img)
blob := NewMat()
defer blob.Close()
BlobFromImages(imgs, &blob, 1.0, image.Pt(img.Size()[0], img.Size()[1]), NewScalar(0, 0, 0, 0), false, false, MatTypeCV32F)
imgsFromBlob := make([]Mat, len(imgs))
ImagesFromBlob(blob, imgsFromBlob)
for i := 0; i < len(imgs); i++ {
func() {
imgFromBlob := NewMat()
defer imgFromBlob.Close()
imgsFromBlob[i].ConvertTo(&imgFromBlob, imgs[i].Type())
diff := NewMat()
defer diff.Close()
Compare(imgs[i], imgFromBlob, &diff, CompareNE)
nz := CountNonZero(diff)
if nz != 0 {
t.Error("imgFromBlob is different from img!")
}
}()
}
}
func TestGetBlobChannel(t *testing.T) {
img := NewMatWithSize(100, 100, 5+16)
defer img.Close()
blob := BlobFromImage(img, 1.0, image.Pt(0, 0), NewScalar(0, 0, 0, 0), true, false)
defer blob.Close()
ch2 := GetBlobChannel(blob, 0, 1)
defer ch2.Close()
if ch2.Empty() {
t.Errorf("GetBlobChannel failed to retrieve 2nd chan of a 3channel blob")
}
if ch2.Rows() != img.Rows() || ch2.Cols() != img.Cols() {
t.Errorf("GetBlobChannel: retrieved image size does not match original")
}
}
func TestGetBlobSize(t *testing.T) {
img := NewMatWithSize(100, 100, 5+16)
defer img.Close()
blob := BlobFromImage(img, 1.0, image.Pt(0, 0), NewScalar(0, 0, 0, 0), true, false)
defer blob.Close()
sz := GetBlobSize(blob)
if sz.Val1 != 1 || sz.Val2 != 3 || sz.Val3 != 100 || sz.Val4 != 100 {
t.Errorf("GetBlobSize retrieved wrong values")
}
}
func TestParseNetBackend(t *testing.T) {
val := ParseNetBackend("halide")
if val != NetBackendHalide {
t.Errorf("ParseNetBackend invalid")
}
val = ParseNetBackend("openvino")
if val != NetBackendOpenVINO {
t.Errorf("ParseNetBackend invalid")
}
val = ParseNetBackend("opencv")
if val != NetBackendOpenCV {
t.Errorf("ParseNetBackend invalid")
}
val = ParseNetBackend("vulkan")
if val != NetBackendVKCOM {
t.Errorf("ParseNetBackend invalid")
}
val = ParseNetBackend("cuda")
if val != NetBackendCUDA {
t.Errorf("ParseNetBackend invalid")
}
val = ParseNetBackend("crazytrain")
if val != NetBackendDefault {
t.Errorf("ParseNetBackend invalid")
}
}
func TestParseNetTarget(t *testing.T) {
val := ParseNetTarget("cpu")
if val != NetTargetCPU {
t.Errorf("ParseNetTarget invalid")
}
val = ParseNetTarget("fp32")
if val != NetTargetFP32 {
t.Errorf("ParseNetTarget invalid")
}
val = ParseNetTarget("fp16")
if val != NetTargetFP16 {
t.Errorf("ParseNetTarget invalid")
}
val = ParseNetTarget("vpu")
if val != NetTargetVPU {
t.Errorf("ParseNetTarget invalid")
}
val = ParseNetTarget("cuda")
if val != NetTargetCUDA {
t.Errorf("ParseNetTarget invalid")
}
val = ParseNetTarget("vulkan")
if val != NetTargetVulkan {
t.Errorf("ParseNetTarget invalid")
}
val = ParseNetTarget("fpga")
if val != NetTargetFPGA {
t.Errorf("ParseNetTarget invalid")
}
val = ParseNetTarget("cudafp16")
if val != NetTargetCUDAFP16 {
t.Errorf("ParseNetTarget invalid")
}
val = ParseNetTarget("idk")
if val != NetTargetCPU {
t.Errorf("ParseNetTarget invalid")
}
}
func TestFP16BlobFromImage(t *testing.T) {
img := NewMatWithSize(100, 100, 5+16)
defer img.Close()
data := FP16BlobFromImage(img, 1.0, image.Pt(100, 100), 0, false, false)
if len(data) != 60000 {
t.Errorf("FP16BlobFromImage incorrect length: %v\n", len(data))
}
img2 := NewMatWithSize(100, 50, 5+16)
defer img2.Close()
data = FP16BlobFromImage(img2, 2.0, image.Pt(50, 100), -0.1, true, false)
if len(data) != 30000 {
t.Errorf("FP16BlobFromImage incorrect length: %v\n", len(data))
}
}
func TestNMSBoxes(t *testing.T) {
img := IMRead("images/face.jpg", IMReadColor)
if img.Empty() {
t.Error("Invalid Mat in NMSBoxes test")
}
defer img.Close()
img.ConvertTo(&img, MatTypeCV32F)
bboxes := []image.Rectangle{
image.Rect(53, 47, 589, 451),
image.Rect(118, 54, 618, 450),
image.Rect(53, 66, 605, 480),
image.Rect(111, 65, 630, 480),
image.Rect(156, 51, 640, 480),
}
scores := []float32{0.82094115, 0.7998236, 0.9809663, 0.99717456, 0.89628726}
scoreThreshold := float32(0.5)
nmsThreshold := float32(0.4)
indices := NMSBoxes(bboxes, scores, scoreThreshold, nmsThreshold)
if indices[0] != 3 {
t.Errorf("Invalid NMSBoxes test indices: %v", indices)
}
}
func TestNMSBoxesWithParams(t *testing.T) {
img := IMRead("images/face.jpg", IMReadColor)
if img.Empty() {
t.Error("Invalid Mat in NMSBoxesWithParams test")
}
defer img.Close()
img.ConvertTo(&img, MatTypeCV32F)
bboxes := []image.Rectangle{
image.Rect(53, 47, 589, 451),
image.Rect(118, 54, 618, 450),
image.Rect(53, 66, 605, 480),
image.Rect(111, 65, 630, 480),
image.Rect(156, 51, 640, 480),
}
scores := []float32{0.82094115, 0.7998236, 0.9809663, 0.99717456, 0.89628726}
scoreThreshold := float32(0.5)
nmsThreshold := float32(0.4)
indices := NMSBoxesWithParams(bboxes, scores, scoreThreshold, nmsThreshold, float32(1.0), 0)
if indices[0] != 3 {
t.Errorf("Invalid NMSBoxesWithParams test indices: %v", indices)
}
}