robocar-road/part/opencv_test.go

194 lines
4.9 KiB
Go

package part
import (
"fmt"
"github.com/cyrilix/robocar-protobuf/go/events"
log "github.com/sirupsen/logrus"
"gocv.io/x/gocv"
"image"
"image/color"
"testing"
)
func toGray(imgColor gocv.Mat) *gocv.Mat {
imgGray := gocv.NewMatWithSize(imgColor.Rows(), imgColor.Cols(), gocv.MatTypeCV8UC1)
gocv.CvtColor(imgColor, &imgGray, gocv.ColorRGBToGray)
return &imgGray
}
func image1() *gocv.Mat {
img := gocv.IMRead("testdata/image.jpg", gocv.IMReadColor)
return &img
}
func image2() *gocv.Mat {
img := gocv.IMRead("testdata/image2.jpg", gocv.IMReadColor)
return &img
}
func image3() *gocv.Mat {
img := gocv.IMRead("testdata/image3.jpg", gocv.IMReadColor)
return &img
}
func image4() *gocv.Mat {
img := gocv.IMRead("testdata/image4.jpg", gocv.IMReadColor)
return &img
}
func image5() *gocv.Mat {
img := gocv.IMRead("testdata/image5.jpg", gocv.IMReadColor)
return &img
}
func TestRoadDetection_DetectRoadContour(t *testing.T) {
rd := NewRoadDetector()
img1 := image1()
defer img1.Close()
img2 := image2()
defer img2.Close()
img3 := image3()
defer img3.Close()
img4 := image4()
defer img4.Close()
img5 := image5()
defer img5.Close()
cases := []struct {
name string
img *gocv.Mat
horizon int
expectedContour []image.Point
}{
{"image1", img1, 20,
[]image.Point{image.Point{0, 45}, image.Point{0, 127}, image.Point{144, 127}, image.Point{95, 21}, image.Point{43, 21}},
},
{"image2", img2, 20,
[]image.Point{{159,69}, {128,53}, {125,41}, {113,42}, {108,21}, {87,21}, {79,41}, {72,30}, {44,39}, {29,34}, {0,67}, {0,127}, {159,127}, {152,101},},
},
{"image3", img3, 20,
[]image.Point{{97,21}, {59,127}, {159,127}, {159,36}, {138,21},},
},
{"image4", img4, 20,
[]image.Point{{0,21}, {0,77}, {68,22}, {0,96}, {0,127}, {159,127}, {159,21},},
},
{"image5", img5, 20,
[]image.Point{{159,32}, {100,36}, {29,60}, {0,79}, {0,127}, {159,127},},
},
}
for _, c := range cases {
imgGray := toGray(*c.img)
contours := rd.DetectRoadContour(imgGray, c.horizon)
imgGray.Close()
log.Infof("[%v] contour: %v", c.name, *contours)
if len(*contours) != len(c.expectedContour) {
t.Errorf("[%v] bad contour size: %v point(s), wants %v", c.name, len(*contours), len(c.expectedContour))
}
for idx, pt := range c.expectedContour {
if pt != (*contours)[idx] {
t.Errorf("[%v] bad point: %v, wants %v", c.name, (*contours)[idx], pt)
}
}
debugContour(*c.img, contours, fmt.Sprintf("/tmp/%v.jpg", c.name))
}
}
func debugContour(img gocv.Mat, contour *[]image.Point, imgPath string) {
imgColor := img.Clone()
defer imgColor.Close()
gocv.DrawContours(&imgColor, [][]image.Point{*contour,}, 0, color.RGBA{
R: 0,
G: 255,
B: 0,
A: 255,
}, 1)
gocv.IMWrite(imgPath, imgColor)
}
func TestRoadDetector_ComputeEllipsis(t *testing.T) {
rd := NewRoadDetector()
cases := []struct {
name string
contour []image.Point
expectedEllipse events.Ellipse
}{
{"image1",
[]image.Point{image.Point{0, 45}, image.Point{0, 127}, image.Point{144, 127}, image.Point{95, 21}, image.Point{43, 21}},
events.Ellipse{
Center: &events.Point{
X: 71,
Y: 87,
},
Width: 139,
Height: 176,
Angle: 92.66927,
Confidence: 1.,
},
},
{"image2",
[]image.Point{{159,69}, {128,53}, {125,41}, {113,42}, {108,21}, {87,21}, {79,41}, {72,30}, {44,39}, {29,34}, {0,67}, {0,127}, {159,127}, {152,101},},
events.Ellipse{
Center: &events.Point{
X: 77,
Y: 102,
},
Width: 152,
Height: 168,
Angle: 94.70433,
Confidence: 1.,
},
},
{"image3",
[]image.Point{{97,21}, {59,127}, {159,127}, {159,36}, {138,21},},
events.Ellipse{
Center: &events.Point{
X: 112,
Y: 86,
},
Width: 122,
Height: 140,
Angle: 20.761106,
Confidence: 1.,
},
},
{"image4",
[]image.Point{{0,21}, {0,77}, {68,22}, {0,96}, {0,127}, {159,127}, {159,21},},
events.Ellipse{
Center: &events.Point{
X: 86,
Y: 78,
},
Width: 154,
Height: 199,
Angle: 90.45744,
Confidence: 1.,
},
},
{"image5",
[]image.Point{{159,32}, {100,36}, {29,60}, {0,79}, {0,127}, {159,127},},
events.Ellipse{
Center: &events.Point{
X: 109,
Y: 87,
},
Width: 103,
Height: 247,
Angle: 79.6229,
Confidence: 1.0,
},
},
}
for _, c := range cases{
ellipse := rd.ComputeEllipsis(&c.contour)
if ellipse.String() != c.expectedEllipse.String(){
t.Errorf("ComputeEllipsis(%v): %v, wants %v", c.name, ellipse.String(), c.expectedEllipse.String())
}
}
}