Any way to get pointer to the "int rows" variable of a Mat?

I’m trying to get an int* to the value held in the rows variable. This is unfortunately necessary to work correctly with some external code I am working with that uses this to schedule how many threads will be used to process the data. Unfortunately despite identifying the layout of Mat, I am not sure how I could get a pointer for this specific variable. Is there any way that this could be done?

Edit:
I have so far managed to get a pointer by converting the CvMat* to an int*, then taking the third “array” element as a pointer (&ptr[2]), however I feel like this is not necessarily a safe thing to do. Could anyone confirm if this is ok?

Based on some testing this seems to return the correct result in my tests so far.

I have looked at this link to identify the layout of the Mat itself.

that SO question you found is 11 years old.

that’s something you shouldn’t touch at all. it is not even supposed to exist anymore. There is no C API anymore. what version of OpenCV are you using? there is no support for outdated versions.

if you need a pointer, make a local variable and copy the value in there.

please try to explain that situation, show some MRE using this.

why a pointer ? what do you expect to happen if you assign / change it ?

Sorry, my mistake. I am using a compiled library and interacting with it through C# so I am not the most familiar with the native code. I unfortunately can’t make a copy, as the code relies heavily on parallelism and requires being able to schedule work based on the length of the mat after an earlier task.

With the current API, I need a pointer to rows prior to scheduling the first task (in this case one that finds contours) that is then used to schedule further parallel tasks after the first task is complete. Unfortunately this must all be done before any of the tasks execute, as the worker threads run independent of the main thread. This means that there is no way to “know” when the first task is complete without significantly affecting performance.

The pointer is required as I am interacting with it through C# and must pass a “reference” to the value before scheduling a number of parallel tasks. It does not modify the value, only reads it in between two scheduled tasks.

sorry, it’s still unclear, what the actual task is (MRE or similar ?)
and it sounds less & less likely, that you’re on the correct path.

the cv::Mat’s int row member is sorta ‘read-only’ . it contains the number of current image rows. manipulating this wont do anything useful (w/o changing other internal struct like stride as well).

are you confusing the Mat header with the pixels ?

omg, you’re re-inventing parallel (data) processing from a wrapper language on top of c++ ? AND abusing a library which also handles this internally in a probably different way ?

I don’t think that saying it like that is justified.
I’m building an application with Unity using opencvsharp and attempting to parallelise some longer processes to improve performance on mobile. I am using Unity’s job system for task scheduling, which is specifically designed to use an int* pointer as it is designed to be used with C++ allocated memory for computer vision applications.

What I was trying to do in this case, was schedule a job to find contours, after which a parallel job would be scheduled which would process each contour further in parallel. For this, Unity provides a function which uses an integer pointer (which they use similarly for their own implementation of unmanaged arrays) to schedule the parallel jobs after the first job completes. The parallel job is scheduled by passing the first job as a dependency, meaning it can run automatically as soon as the first job finishes. I am not trying to reinvent anything.

No offence, but as moderators on this website I would expect nicer behaviour than what I have seen here.

ok. we all misread it (including the title and 400 lines you posted !) and what you wanted in the end is (probably) the data pointer to a specific row:

if (mat.type() == CV_8UC3) // 3 bytes
    Vec3b * ptr = mat.ptr<Vec3b>(row);
else if (mat.type() == CV_32F) // 1 float
    float *ptr = mat.ptr<float>(row);

note, that there is no int* here , unless you cast from CV_8U4

also, please look at current tutorials

Sorry, its a slightly difficult thing to explain. Its not a row I am trying to get a pointer to but the memory address that the number of rows is stored in (hence rows).

The result of findContours produces a Mat that contains the address for the Mats containing the contours themselves. To work correctly, the thread scheduling needs a way to determine how many threads to start. I would like to create the same amount of threads as the number of contours found in the first job, hence why I would need to have a pointer to the number of rows in the Mat produced by findContours. For this I would need a pointer to memory where the “rows” variable is stored, not a pointer to a row in the Mat.

Unfortunately as I am handing the work to a thread handler, I have no way to check when the first job ends and the second begins, therefore I need to tell the system where to look before the jobs are scheduled, which the system handles by taking a pointer to the “thread count”, which in this case would need to be the rows variable. This is checked after the first job finishes, just before the thread manager starts the second job.

you don’t need that. some API needs that.

and it doesn’t. it just wants that. or you think it does.

there’s no need to pass this value as a pointer. pass it as a value. whatever API you use has no business getting a pointer to this value. it’s not gonna change the value.

how about you show us what you’re talking about? you haven’t presented this weird API that wants a pointer to a number.

https://docs.unity3d.com/Packages/com.unity.jobs@0.0/api/Unity.Jobs.IJobParallelForDeferExtensions.html
The function I am referring to is Schedule(T, Int32*, Int32, JobHandle)

The reason it takes a pointer instead of the value is because at the time of scheduling (before any of the jobs have begun) the Mat of contours has not been filled yet (it will be filled by the first job). The system will read the value at the pointer only after the first job has completed, but needs to know where to look prior to any job starting. It never needs to change this value, the pointer is used more as a getter at the end of the first job to create threads for the parallel second job.

You can see more about how this job works at Interface IJobParallelForDefer | Package Manager UI website

wrong again. you’re supposed to feed it a vector<Mat> and there are no ‘addresses’ involved (on c++ level) Mat’s are not a collection of ‘row’ pointers.

and sorry, do not expect anyone here to know the internals of your c# wrapper, it’s far too much a ‘fringe’ thing, and usually off-topic.

“dependsOn”…

how about you make your own Int32, somewhere, and coordinate the reading and writing of it at the appropriate times?

you really need to take this to a Unity forum. that API sounds insane to me and can’t possibly be how people are supposed to use it. I refuse to believe that you’re supposed to poke around in a random library’s (OpenCV) structures like that. I believe you’re supposed to make your own Int32 somewhere and set it to whatever you need at the end of the first job.

re that “Mat containing addresses”… we can’t help if you come up with beliefs about OpenCV’s inner workings that are plain false.

1 Like