Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Severe Memory Leak During Conversion between Image and gocv.Mat #1159

Open
Sclock opened this issue Mar 25, 2024 · 1 comment
Open

Severe Memory Leak During Conversion between Image and gocv.Mat #1159

Sclock opened this issue Mar 25, 2024 · 1 comment
Labels

Comments

@Sclock
Copy link

Sclock commented Mar 25, 2024

Description

In this issue, it is reported that there is a severe memory leak during the conversion between image.Image and gocv.Mat types, specifically when these conversions are done within a goroutine pool. Despite the fact that all the images are reported as Empty, a significant amount

Steps to Reproduce

package main  
  
import (  
	"fmt"  
	"image"  
	"time"  
  
	"github.com/panjf2000/ants"  
	"gocv.io/x/gocv"  
)  
  
// MatToMat converts a gocv.Mat to another gocv.Mat through an image representation  
func MatToMat(mat gocv.Mat) gocv.Mat {  
	// Convert gocv.Mat to image.Image  
	img, _ := mat.ToImage()  
  
	// Convert image.Image back to gocv.Mat (RGB format)  
	reImg, _ := gocv.ImageToMatRGB(img)  
  
	// Ensure the new gocv.Mat is closed to prevent memory leaks  
	defer reImg.Close()  
  
	return reImg  
}  
  
// ImgToImg converts an image.Image to another image.Image through a gocv.Mat representation  
func ImgToImg(img image.Image) image.Image {  
	// Convert image.Image to gocv.Mat (RGB format)  
	mat, _ := gocv.ImageToMatRGB(img)  
  
	// Convert gocv.Mat back to image.Image  
	reImg, _ := mat.ToImage()  
  
	return reImg  
}  
  
// imgInfo holds an image's gocv.Mat representation and its name  
type imgInfo struct {  
	img  gocv.Mat  
	name string  
}  
  
// sendGocv is a channel used to send imgInfo instances  
var sendGocv = make(chan imgInfo)  
  
// imgdict is a map that stores imgInfo instances  
var imgdict = make(map[string]gocv.Mat)  
  
// poolWait waits for all images to be processed and stored in imgdict  
func poolWait(count int) {  
	for {  
		select {  
		case imginfo := <-sendGocv:  
			imgdict[imginfo.name] = imginfo.img  
			count--  
			// fmt.Println("Remaining", count, "Processed", len(imgdict))  
			if count == 0 {  
				return  
			}  
		}  
	}  
}  
  
// createAndRunPool creates a goroutine pool to run a specified task multiple times  
func createAndRunPool(count, poolSize int, task func(text string)) {  
	p, err := ants.NewPool(poolSize)  
	if err != nil {  
		panic(err)  
	}  
	defer p.Release()  
  
	go func() {  
		for i := 0; i < count; i++ {  
			err = p.Submit(func() {  
				msg := fmt.Sprintf("%d", i)  
				task(msg)  
			})  
			if err != nil {  
				panic(err)  
			}  
		}  
	}()  
	poolWait(count)  
}  
  
func main() {  
	file := "./any_png.png"  
	runCount := 100  
  
	mat := gocv.IMRead(file, gocv.IMReadUnchanged)  
  
	fmt.Println("first")  
	createAndRunPool(runCount, 20, func(text string) {  
		newMat := MatToMat(mat)  
		sendGocv <- imgInfo{newMat, text}  
	})  
	fmt.Println("end")  
  
	time.Sleep(5 * time.Second)  
  
	fmt.Println("Second round")  
	createAndRunPool(runCount, 20, func(text string) {  
		newMat := MatToMat(mat)  
		sendGocv <- imgInfo{newMat, text}  
	})  
	fmt.Println("End")  
  
	time.Sleep(5 * time.Second)  
  
	for _, ig := range imgdict {  
		if ig.Empty() {  
			fmt.Println("Empty!")  
		}  
	}  
}

Your Environment

  • Operating System and version: Linux 5.4.0-126-generic Feature/mat pointer #142-Ubuntu SMP Fri Aug 26 12:12:57 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
  • OpenCV version used: 4.8.1
  • How did you install OpenCV? make build
  • GoCV version used: v0.35.0
  • Go version: 1.22.1
  • Did you run the env.sh or env.cmd script before trying to go run or go build?

If my usage method is incorrect, please tell me the correct usage. Thank you

@deadprogram
Copy link
Member

Hello @Sclock please see https://github.com/hybridgroup/gocv?tab=readme-ov-file#profiling for explanation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants