mirror of https://bitbucket.org/ausocean/av.git
improved corner detection in transform function, fixed some comments
This commit is contained in:
parent
2ec62db850
commit
77c803e4bd
|
@ -29,14 +29,14 @@ package main
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
// Struct to hold the results of the turbidity sensor.
|
// Results holds the results of the turbidity sensor.
|
||||||
type Results struct {
|
type Results struct {
|
||||||
Turbidity []float64
|
Turbidity []float64
|
||||||
Saturation []float64
|
Saturation []float64
|
||||||
Contrast []float64
|
Contrast []float64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Results constructor
|
// NewResults constructs the results object.
|
||||||
func NewResults(n int) (*Results, error) {
|
func NewResults(n int) (*Results, error) {
|
||||||
|
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
|
@ -51,7 +51,7 @@ func NewResults(n int) (*Results, error) {
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update results to add new values at specified index.
|
// Update adds new values to slice at specified index.
|
||||||
func (r *Results) Update(newSat, newCont, newTurb float64, index int) {
|
func (r *Results) Update(newSat, newCont, newTurb float64, index int) {
|
||||||
r.Saturation[index] = newSat
|
r.Saturation[index] = newSat
|
||||||
r.Contrast[index] = newCont
|
r.Contrast[index] = newCont
|
||||||
|
|
|
@ -40,24 +40,37 @@ import (
|
||||||
// TurbiditySensor is a software based turbidity sensor that uses CV to determine saturation and constrast level
|
// TurbiditySensor is a software based turbidity sensor that uses CV to determine saturation and constrast level
|
||||||
// of a chessboard-like target submerged in water that can be correlated to turbidity/visibility values.
|
// of a chessboard-like target submerged in water that can be correlated to turbidity/visibility values.
|
||||||
type TurbiditySensor struct {
|
type TurbiditySensor struct {
|
||||||
template, standard gocv.Mat
|
template, templateCorners gocv.Mat
|
||||||
k1, k2, sobelFilterSize int
|
standard, standardCorners gocv.Mat
|
||||||
scale, alpha float64
|
k1, k2, sobelFilterSize int
|
||||||
|
scale, alpha float64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turbidity sensor constructor.
|
// NewTurbiditySensor constructor for a turbidity sensor.
|
||||||
func NewTurbiditySensor(template, standard gocv.Mat, k1, k2, sobelFilterSize int, scale, alpha float64) (*TurbiditySensor, error) {
|
func NewTurbiditySensor(template, standard gocv.Mat, k1, k2, sobelFilterSize int, scale, alpha float64) (*TurbiditySensor, error) {
|
||||||
ts := new(TurbiditySensor)
|
ts := new(TurbiditySensor)
|
||||||
|
templateCorners := gocv.NewMat()
|
||||||
|
standardCorners := gocv.NewMat()
|
||||||
|
|
||||||
|
// Validate template image is not empty and has valid corners.
|
||||||
if template.Empty() {
|
if template.Empty() {
|
||||||
return nil, errors.New("template image is empty.")
|
return nil, errors.New("template image is empty.")
|
||||||
}
|
}
|
||||||
|
if !gocv.FindChessboardCorners(template, image.Pt(3, 3), &templateCorners, gocv.CalibCBNormalizeImage) {
|
||||||
|
return nil, errors.New("could not find corners in template image")
|
||||||
|
}
|
||||||
ts.template = template
|
ts.template = template
|
||||||
|
ts.templateCorners = templateCorners
|
||||||
|
|
||||||
|
// Validate standard image is not empty and has valid corners.
|
||||||
if standard.Empty() {
|
if standard.Empty() {
|
||||||
return nil, errors.New("standard image is empty.")
|
return nil, errors.New("standard image is empty.")
|
||||||
}
|
}
|
||||||
|
if !gocv.FindChessboardCorners(standard, image.Pt(3, 3), &standardCorners, gocv.CalibCBNormalizeImage) {
|
||||||
|
return nil, errors.New("could not find corners in standard image")
|
||||||
|
}
|
||||||
ts.standard = standard
|
ts.standard = standard
|
||||||
|
ts.standardCorners = standardCorners
|
||||||
|
|
||||||
ts.k1, ts.k2, ts.sobelFilterSize = k1, k2, sobelFilterSize
|
ts.k1, ts.k2, ts.sobelFilterSize = k1, k2, sobelFilterSize
|
||||||
ts.alpha, ts.scale = alpha, scale
|
ts.alpha, ts.scale = alpha, scale
|
||||||
|
@ -127,6 +140,7 @@ func (ts TurbiditySensor) EvaluateImage(img, edge gocv.Mat) (float64, float64, e
|
||||||
return sharpness, contrast, nil
|
return sharpness, contrast, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// minMax returns the max and min pixel values of an image block.
|
||||||
func (ts TurbiditySensor) minMax(img gocv.Mat, xStart, yStart, xEnd, yEnd int) (float64, float64) {
|
func (ts TurbiditySensor) minMax(img gocv.Mat, xStart, yStart, xEnd, yEnd int) (float64, float64) {
|
||||||
max := -math.MaxFloat64
|
max := -math.MaxFloat64
|
||||||
min := math.MaxFloat64
|
min := math.MaxFloat64
|
||||||
|
@ -147,7 +161,7 @@ func (ts TurbiditySensor) minMax(img gocv.Mat, xStart, yStart, xEnd, yEnd int) (
|
||||||
return max, min
|
return max, min
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate a block within an image and return the value to be added to the sharpness result.
|
// evaluateBlockEME will evaluate an image block and return the value to be added to the sharpness result.
|
||||||
func (ts TurbiditySensor) evaluateBlockEME(img gocv.Mat, xStart, yStart, xEnd, yEnd int) float64 {
|
func (ts TurbiditySensor) evaluateBlockEME(img gocv.Mat, xStart, yStart, xEnd, yEnd int) float64 {
|
||||||
max, min := ts.minMax(img, xStart, yStart, xEnd, yEnd)
|
max, min := ts.minMax(img, xStart, yStart, xEnd, yEnd)
|
||||||
|
|
||||||
|
@ -158,7 +172,7 @@ func (ts TurbiditySensor) evaluateBlockEME(img gocv.Mat, xStart, yStart, xEnd, y
|
||||||
return 0.0
|
return 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate a block within an image and return the value to be added to the contrast result.
|
// evaluateBlockAMEE will evaluate an image block and return the value to be added to the contrast result.
|
||||||
func (ts TurbiditySensor) evaluateBlockAMEE(img gocv.Mat, xStart, yStart, xEnd, yEnd int) float64 {
|
func (ts TurbiditySensor) evaluateBlockAMEE(img gocv.Mat, xStart, yStart, xEnd, yEnd int) float64 {
|
||||||
max, min := ts.minMax(img, xStart, yStart, xEnd, yEnd)
|
max, min := ts.minMax(img, xStart, yStart, xEnd, yEnd)
|
||||||
|
|
||||||
|
@ -174,29 +188,19 @@ func (ts TurbiditySensor) evaluateBlockAMEE(img gocv.Mat, xStart, yStart, xEnd,
|
||||||
func (ts TurbiditySensor) transform(img gocv.Mat) (gocv.Mat, error) {
|
func (ts TurbiditySensor) transform(img gocv.Mat) (gocv.Mat, error) {
|
||||||
out := gocv.NewMat()
|
out := gocv.NewMat()
|
||||||
mask := gocv.NewMat()
|
mask := gocv.NewMat()
|
||||||
corners_img := gocv.NewMat()
|
imgCorners := gocv.NewMat()
|
||||||
corners_template := gocv.NewMat()
|
|
||||||
|
|
||||||
// Check image is valid.
|
// Check image is valid.
|
||||||
if img.Empty() {
|
if img.Empty() {
|
||||||
return out, errors.New("image is empty, cannot transform")
|
return out, errors.New("image is empty, cannot transform")
|
||||||
}
|
}
|
||||||
|
// Check image for corners, if non can be found corners will be set to default value.
|
||||||
// Find corners in image.
|
if !gocv.FindChessboardCorners(img, image.Pt(3, 3), &imgCorners, gocv.CalibCBFastCheck) {
|
||||||
if !gocv.FindChessboardCorners(img, image.Pt(3, 3), &corners_img, gocv.CalibCBNormalizeImage) {
|
imgCorners = ts.standardCorners
|
||||||
// Apply default if transformation fails.
|
|
||||||
if !gocv.FindChessboardCorners(ts.standard, image.Pt(3, 3), &corners_img, gocv.CalibCBNormalizeImage) {
|
|
||||||
return out, errors.New("Could not find corners in default image")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find corners in template.
|
|
||||||
if !gocv.FindChessboardCorners(ts.template, image.Pt(3, 3), &corners_template, gocv.CalibCBNormalizeImage) {
|
|
||||||
return out, errors.New("Could not find corners in template")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find and apply transformation.
|
// Find and apply transformation.
|
||||||
H := gocv.FindHomography(corners_img, &corners_template, gocv.HomograpyMethodRANSAC, 3.0, &mask, 2000, 0.995)
|
H := gocv.FindHomography(imgCorners, &ts.templateCorners, gocv.HomograpyMethodRANSAC, 3.0, &mask, 2000, 0.995)
|
||||||
gocv.WarpPerspective(img, &out, H, image.Pt(ts.template.Rows(), ts.template.Cols()))
|
gocv.WarpPerspective(img, &out, H, image.Pt(ts.template.Rows(), ts.template.Cols()))
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
|
|
|
@ -59,7 +59,7 @@ func TestImages(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create results
|
// Create results.
|
||||||
results, err := NewResults(nImages)
|
results, err := NewResults(nImages)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
Loading…
Reference in New Issue