mirror of
https://github.com/hybridgroup/gocv
synced 2025-08-25 08:41:04 +08:00
528 lines
13 KiB
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)
|
|
}
|
|
}
|