gocv icon indicating copy to clipboard operation
gocv copied to clipboard

invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation]

Open hariangr opened this issue 2 years ago • 2 comments

Description

Hey, I am working with a Soccer Robot competition and use gocv as its main computer vision library. The robot use two camera and process a lot of data simultaneously using Goroutine (Let's say one for ball, one for goalpost, one for carpet, one for magenta robot etc)

As part of the process to do that, I need to do erode and dilate, and usually it works just fine, but sometimes when I run the project for quite a long time (1 minute+) a segmentation violation would happen

	?:-1
		<unknown>
	?:-1
		<unknown>
	?:-1
		<unknown>
	?:-1
		<unknown>
	?:-1
		<unknown>
	?:-1
		<unknown>
	?:-1
		<unknown>
	?:-1
		<unknown>
	?:-1
		<unknown>
	?:-1
		<unknown>
	?:-1
		<unknown>
	?:-1
		<unknown>
	/Users/hariangr/go/pkg/mod/gocv.io/x/[email protected]/imgproc.cpp:137
		C.Erode
	/tmp/go-build/cgo-gcc-prolog:621
		C._cgo_9685539a886c_Cfunc_Erode
	/usr/local/go/src/runtime/asm_amd64.s:667
		runtime.asmcgocall
	?:-1
		<unknown>
	_cgo_gotypes.go:1497
		gocv.io/x/gocv._Cfunc_Erode
	/Users/hariangr/go/pkg/mod/gocv.io/x/[email protected]/imgproc.go:312
		gocv.io/x/gocv.Erode.func1
	/Users/hariangr/go/pkg/mod/gocv.io/x/[email protected]/imgproc.go:312
		gocv.io/x/gocv.Erode
	/Users/hariangr/Documents/MyFiles/Developer/Robotec/Beroda/golang/BrainFreeze/internal/wanda/haesve/dummy/narrow_dummy.go:56
		harianugrah.com/brainfreeze/internal/wanda/haesve/dummy.(*NarrowHaesveDummy).Detect
	/Users/hariangr/Documents/MyFiles/Developer/Robotec/Beroda/golang/BrainFreeze/internal/wanda/wanda.go:303
		harianugrah.com/brainfreeze/internal/wanda.detectDummy
	/usr/local/go/src/runtime/asm_amd64.s:1371
		runtime.goexit

The thing that frustrate me the most is I can't caught the error using Recover. If error happen I am okay by skipping one or two frame, but closing the entire app is not okay.

The problem happen most in dilate (Especially if I set the kernel to something big like 9 or bigger) and erode (Either small or big kernel). The app would work just fine for a while (Either seconds or even minutes) then just crash

Steps to Reproduce

  1. Do HSV detection using Erode or Dilate

Your Environment

  • Operating System and version: MacOs Big Sur 11.5
  • OpenCV version used: 4.5.2
  • How did you install OpenCV? Using the built in installer of gocv
  • GoCV version used: 0.27.0
  • Go version: go1.16.5 darwin/amd64
  • Did you run the env.sh or env.cmd script before trying to go run or go build? No

hariangr avatar Aug 05 '21 19:08 hariangr

The app looks like this

Screen Shot 2021-08-06 at 03 53 00

And one of the detection class looks like this

package dummy

import (
	"fmt"
	"image/color"

	"gocv.io/x/gocv"
	"harianugrah.com/brainfreeze/pkg/models"
	"harianugrah.com/brainfreeze/pkg/models/configuration"
)

type NarrowHaesveDummy struct {
	conf     *configuration.FreezeConfig
	upperHsv gocv.Scalar
	lowerHsv gocv.Scalar
}

func NewNarrowHaesveDummy(conf *configuration.FreezeConfig) *NarrowHaesveDummy {
	upper := gocv.NewScalar(179, 255, 255, 1)
	lower := gocv.NewScalar(166, 85, 69, 0)

	return &NarrowHaesveDummy{
		conf:     conf,
		upperHsv: upper,
		lowerHsv: lower,
	}
}

// Input adalah Mat yang sudah dalam format hsv
func (n *NarrowHaesveDummy) Detect(hsvFrame *gocv.Mat) (found bool, result []models.DetectionObject) {
	detecteds := []models.DetectionObject{}

	defer func() {
		if r := recover(); r != nil {
			found = false
			result = detecteds
			fmt.Println("recovered from ", r)
			return
		}
	}()

	if hsvFrame.Empty() {
		return false, detecteds
	}

	w := hsvFrame.Cols()
	h := hsvFrame.Rows()

	filtered := gocv.NewMatWithSize(h, w, gocv.MatTypeCV8UC1)
	defer filtered.Close()

	gocv.InRangeWithScalar(*hsvFrame, n.lowerHsv, n.upperHsv, &filtered)

	erodeMat := gocv.Ones(4, 4, gocv.MatTypeCV8UC1)
	defer erodeMat.Close()
	gocv.Erode(filtered, &filtered, erodeMat)

	// dilateMat := gocv.Ones(21, 21, gocv.MatTypeCV8UC1)
	// defer dilateMat.Close()
	// gocv.Dilate(filtered, &filtered, dilateMat)

	c := color.RGBA{75, 100, 0, 0}

	hierarchyMat := gocv.NewMat()
	defer hierarchyMat.Close()

	pointVecs := gocv.FindContoursWithParams(filtered, &hierarchyMat, gocv.RetrievalExternal, gocv.ChainApproxNone)
	defer pointVecs.Close()

	if pointVecs.Size() == 0 {
		return false, detecteds
	}

	for i := 0; i < pointVecs.Size(); i++ {
		it := pointVecs.At(i)
		area := gocv.ContourArea(it)

		if area < n.conf.Wanda.MinimumHsvArea {
			// Skip kalau ukurannya kekecilan
			continue
		}
		if area > n.conf.Wanda.MaximumHsvArea {
			continue
		}

		rect := gocv.BoundingRect(it)
		gocv.Rectangle(hsvFrame, rect, c, 2)
		gocv.PutText(hsvFrame, "Dummy", rect.Min, gocv.FontHersheyPlain, 1.2, c, 2)

		d := models.NewDetectionObject(rect)
		detecteds = append(detecteds, d)
	}

	return true, detecteds
}

Any help would very much appreciated

hariangr avatar Aug 05 '21 19:08 hariangr

Hard to tell from your exact code, but I would try to avoid the modification in place.

Instead of

gocv.Erode(filtered, &filtered, erodeMat)

try

eroded := NewMat()
defer eroded.Close() 
gocv.Erode(filtered, &eroded, erodeMat)

Or something like that. Hope that helps!

deadprogram avatar Aug 09 '21 17:08 deadprogram