CopyTo loding data
I've stepped through the code, through each OpenCV 3.4.0 function, and I just can't understand why data is being lost or destroyed on my faster systems.
When I use CMat::copyTo to send data to a CMat that has already had its frame buffer allocated (I checked, 8MB allocated), and the scope of the receiving CMat is always in range, why should there be a memory problem?
Using clone solves the problem but allocates memory again for the receiving CMat.
CopyTo just memcpy's to the target CMat's data, so it should work. I stepped through the destructors in my copy procedure, and the target CMat receiving the data is not freed.
If I call ShowImg() on the returned data after the copy call, then the memory problem goes away.
Appreciate any advice on this.
My test code to copy a D3D9 surface to a OpenCV CMat:-
void main()
{
while (input() != _ESC)
{
if (!m_pInputLeft)
{
m_pInputLeftRight = new cv::Mat(pSBM->pTexture->getSize().Height, pSBM->pTexture->getSize().Width, CV_8UC4);
// I stepped thro and memory gets allocated, some 8 MBS for an FHD sized frame
}
// *** Copy video frame (DShow RGBA) that was input to OpenCV BGR to LR Mat
if (CopyTextureToMat(pSBM->pTexture, m_pInputLeftRight), 1)
{
DisplayFrame(m_pInputLeftRight); // Frame data does not get displayed if copy mode is copyTo (clone works!)
}
}
}
bool CopyTextureToMat(CD3D9Texture *pD9Tex , cv::Mat *pDest, SBM_P *pParams)
{
IDirect3DSurface9 *pSurf;
if (!pD9Tex || !pDest)
return false;
HRESULT r = pD9Tex->Texture->GetSurfaceLevel(0, &pSurf); // Get DX9 surface from Viva3D texture
if (r != S_OK)
return false;
r = pSurf->LockRect(&memDesc, NULL, D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE); // D3DLOCK_READONLY
if (FAILED(r))
{
if (r == D3DERR_WASSTILLDRAWING)
{
bool b = true; // Debug point only
}
else
if (r == D3DERR_INVALIDCALL)
{
bool b = true;
}
return false;
}
pMatOut = new cv::Mat(iHeight, iWidth, CV_8UC4, memDesc.pBits, memDesc.Pitch); // Create Mat using same memory as DX9 surface
static bool bCopyMode = 0;
if (bCopyMode)
pMatOut->copyTo(*pDest); // On higher speed systems the memory is being destroyed (no exception occurs on use though)
else
{
*pDest = pMatOut->clone(); // This duplicates the data and works on the higher speed systems
}
r = pSurf->UnlockRect();
delete pMatOut;
if (FAILED(r))
return false;
return true;
}
please do NOT use raw pointers and new with cv::Mat. it already has refcounts, and your pointers defeat that purpose. please pass it by reference, or even by value (it's just a 60bytes header)
then, clone() is the same as copyTo(), don't start to believe in voodoo ;)
refactor, start with removing the pointers / new with cv::Mat
Right! Sorry, that makes sense! Funny about the voodoo, when I get confused I do feel like that at times, I guess we all do :)
So I can output the mat like this directly:-
This would be correct?:- If DestMat has an allocated buffer the same size and type, the local mat will copy the data to that, otherwise it will be allocated in the dest mat, or share the memory from the source, the latter right? Then when the local proc cv::Mat is destroyed, it will not free the memory buffer because it is in use by pDest.
if you construct a Mat like:
it will NOT take ownership of the data in any way. no memory will get allocated, some_pointer will not be destroyed. in other words, this one just makes a Mat header around existing data. since your pointer from the dx texture will get invalid, once you leave that function, you'll have to clone (or copy) it, so:
This is where I am confused because stepping through the copyTo() code it does do a memcpy to the destination texture's buffer, so although the source will be lost, the data is copied, as the destination Mat has had a buffer allocated during create. What have I missed???