C to delphi method conversion of openCV sample code - delphi

I have a code snippet from openCV example as follows:
CvScalar sum_line_pixels( IplImage* image, CvPoint pt1, CvPoint pt2 )
{
CvLineIterator iterator;
int blue_sum = 0, green_sum = 0, red_sum = 0;
int count = cvInitLineIterator( image, pt1, pt2, &iterator, 8, 0 );
for( int i = 0; i < count; i++ ){
blue_sum += iterator.ptr[0];
green_sum += iterator.ptr[1];
red_sum += iterator.ptr[2];
CV_NEXT_LINE_POINT(iterator);
/* print the pixel coordinates: demonstrates how to calculate the
coordinates */
{
int offset, x, y;
/* assume that ROI is not set, otherwise need to take it
into account. */
offset = iterator.ptr - (uchar*)(image->imageData);
y = offset/image->widthStep;
x = (offset - y*image->widthStep)/(3*sizeof(uchar)
/* size of pixel */);
printf("(%d,%d)\n", x, y );
}
}
return cvScalar( blue_sum, green_sum, red_sum );
}
I got stuck on the line:
offset = iterator.ptr - (uchar*)(image->imageData);
Iterator structure is:
PCvLineIterator = ^TCvLineIterator;
TCvLineIterator = packed record
ptr: ^UCHAR;
err: Integer;
plus_delta: Integer;
minus_delta: Integer;
plus_step: Integer;
minus_step: Integer;
end;
image->imageData is
imageData: PByte;
Could someone help me convert the offset line to delphi?
Thanks!

The line that calculates offset is simply calculating the number of bytes between the pointers iterator.ptr and image->imageData. Assuming you are using the same variable names a Delphi version of that code would be like this:
offset := PByte(iterator.ptr) - image.ImageData;
However, since you are using an older version of Delphi, the above code will not compile. Older Delphi versions (pre Delphi 2009) don't permit pointer arithmetic on types other than PAnsiChar. So you will need to write it like this:
offset := PAnsiChar(iterator.ptr) - PAnsiChar(image.ImageData);
I suspect that what is confusing you in the C code is (uchar*). That is the C syntax for a type cast.
As an aside, it is a mistake to use packed records for OpenCV structs. If you take a look at the C header files you will see that these structs are not packed. This is benign in the case of CvLineIterator since it has no padding, but you will get caught out somewhere down the line if you get into the bad habit of packing structs that should not be packed.

Related

Using opencv's calcHist with UMat for calculating a percentile

I am writing a function that gets a given percentile of an image (gray).
For that I wanted to use calcHist() with UMat in order to accelerate my code.
But in all the ways I've tried to do that - it took much more time when I used UMat (instead of Mat).
I am new here - any help would be highly appreciated.
Here is my code:
int CalcPercentile(UMat gray, float fPercent)
{
int hSize = 256;
UMat hist;
Mat histMat;
calcHist(vector<UMat>{gray}, vector<int>{0}, UMat(), hist, vector<int>{hSize}, vector<float>{0,255});
int iNumPixels = gray.rows * gray.cols;
float fSumFreqNeeded = (float)iNumPixels * fPercent;
histMat = hist.getMat(ACCESS_READ); // or: hist.copyTo(histMat);
int iSumFreq = 0, iVal;
for (iVal = 0; iVal < iHistSize; iVal++)
{
int iCurrFreq = (int)(histMat.at<float>(iVal));
iSumFreq += iCurrFreq;
if (iSumFreq >= fSumFreqNeeded)
break;
}
return iVal;
}
a corresponding function with Mat instead of UMat was much faster.
(But my code uses UMat gray image as input - and converting to Mat again takes too much time).

OpenCL :Access proper index by using globalid(.)

Hi,
I am coding in OpenCL.
I am converting a "C function" having 2D array starting from i=1 and j=1 .PFB .
cv::Mat input; //Input :having some data in it ..
//Image input size is :input.rows=288 ,input.cols =640
cv::Mat output(input.rows-2,input.cols-2,CV_32F); //Output buffer
//Image output size is :output.rows=286 ,output.cols =638
This is a code Which I want to modify in OpenCL:
for(int i=1;i<output.rows-1;i++)
{
for(int j=1;j<output.cols-1;j++)
{
float xVal = input.at<uchar>(i-1,j-1)-input.at<uchar>(i-1,j+1)+ 2*(input.at<uchar>(i,j-1)-input.at<uchar>(i,j+1))+input.at<uchar>(i+1,j-1) - input.at<uchar>(i+1,j+1);
float yVal = input.at<uchar>(i-1,j-1) - input.at<uchar>(i+1,j-1)+ 2*(input.at<uchar>(i-1,j) - input.at<uchar>(i+1,j))+input.at<uchar>(i-1,j+1)-input.at<uchar>(i+1,j+1);
output.at<float>(i-1,j-1) = xVal*xVal+yVal*yVal;
}
}
...
Host code :
//Input Image size is :input.rows=288 ,input.cols =640
//Output Image size is :output.rows=286 ,output.cols =638
OclStr->global_work_size[0] =(input.cols);
OclStr->global_work_size[1] =(input.rows);
size_t outBufSize = (output.rows) * (output.cols) * 4;//4 as I am copying all 4 uchar values into one float variable space
cl_mem cl_input_buffer = clCreateBuffer(
OclStr->context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR ,
(input.rows) * (input.cols),
static_cast<void *>(input.data), &OclStr->returnstatus);
cl_mem cl_output_buffer = clCreateBuffer(
OclStr->context, CL_MEM_WRITE_ONLY| CL_MEM_USE_HOST_PTR ,
(output.rows) * (output.cols) * sizeof(float),
static_cast<void *>(output.data), &OclStr->returnstatus);
OclStr->returnstatus = clSetKernelArg(OclStr->objkernel, 0, sizeof(cl_mem), (void *)&cl_input_buffer);
OclStr->returnstatus = clSetKernelArg(OclStr->objkernel, 1, sizeof(cl_mem), (void *)&cl_output_buffer);
OclStr->returnstatus = clEnqueueNDRangeKernel(
OclStr->command_queue,
OclStr->objkernel,
2,
NULL,
OclStr->global_work_size,
NULL,
0,
NULL,
NULL
);
clEnqueueMapBuffer(OclStr->command_queue, cl_output_buffer, true, CL_MAP_READ, 0, outBufSize, 0, NULL, NULL, &OclStr->returnstatus);
kernel Code :
__kernel void Sobel_uchar (__global uchar *pSrc, __global float *pDstImage)
{
const uint cols = get_global_id(0)+1;
const uint rows = get_global_id(1)+1;
const uint width= get_global_size(0);
uchar Opsoble[8];
Opsoble[0] = pSrc[(cols-1)+((rows-1)*width)];
Opsoble[1] = pSrc[(cols+1)+((rows-1)*width)];
Opsoble[2] = pSrc[(cols-1)+((rows+0)*width)];
Opsoble[3] = pSrc[(cols+1)+((rows+0)*width)];
Opsoble[4] = pSrc[(cols-1)+((rows+1)*width)];
Opsoble[5] = pSrc[(cols+1)+((rows+1)*width)];
Opsoble[6] = pSrc[(cols+0)+((rows-1)*width)];
Opsoble[7] = pSrc[(cols+0)+((rows+1)*width)];
float gx = Opsoble[0]-Opsoble[1]+2*(Opsoble[2]-Opsoble[3])+Opsoble[4]-Opsoble[5];
float gy = Opsoble[0]-Opsoble[4]+2*(Opsoble[6]-Opsoble[7])+Opsoble[1]-Opsoble[5];
pDstImage[(cols-1)+(rows-1)*width] = gx*gx + gy*gy;
}
Here I am not able to get the output as expected.
I am having some questions that
My for loop is starting from i=1 instead of zero, then How can I get proper index by using the global_id() in x and y direction
What is going wrong in my above kernel code :(
I am suspecting there is a problem in buffer stride but not able to further break my head as already broke it throughout a day :(
I have observed that with below logic output is skipping one or two frames after some 7/8 frames sequence.
I have added the screen shot of my output which is compared with the reference output.
My above logic is doing partial sobelling on my input .I changed the width as -
const uint width = get_global_size(0)+1;
PFB
Your suggestions are most welcome !!!
It looks like you may be fetching values in (y,x) format in your opencl version. Also, you need to add 1 to the global id to replicate your for loops starting from 1 rather than 0.
I don't know why there is an unused iOffset variable. Maybe your bug is related to this? I removed it in my version.
Does this kernel work better for you?
__kernel void simple(__global uchar *pSrc, __global float *pDstImage)
{
const uint i = get_global_id(0) +1;
const uint j = get_global_id(1) +1;
const uint width = get_global_size(0) +2;
uchar Opsoble[8];
Opsoble[0] = pSrc[(i-1) + (j - 1)*width];
Opsoble[1] = pSrc[(i-1) + (j + 1)*width];
Opsoble[2] = pSrc[i + (j-1)*width];
Opsoble[3] = pSrc[i + (j+1)*width];
Opsoble[4] = pSrc[(i+1) + (j - 1)*width];
Opsoble[5] = pSrc[(i+1) + (j + 1)*width];
Opsoble[6] = pSrc[(i-1) + (j)*width];
Opsoble[7] = pSrc[(i+1) + (j)*width];
float gx = Opsoble[0]-Opsoble[1]+2*(Opsoble[2]-Opsoble[3])+Opsoble[4]-Opsoble[5];
float gy = Opsoble[0]-Opsoble[4]+2*(Opsoble[6]-Opsoble[7])+Opsoble[1]-Opsoble[5];
pDstImage[(i-1) + (j-1)*width] = gx*gx + gy*gy ;
}
I am a bit apprehensive about posting an answer suggesting optimizations to your kernel, seeing as the original output has not been reproduced exactly as of yet. There is a major improvement available to be made for problems related to image processing/filtering.
Using local memory will help you out by reducing the number of global reads by a factor of eight, as well as grouping the global writes together for potential gains with the single write-per-pixel output.
The kernel below reads a block of up to 34x34 from pSrc, and outputs a 32x32(max) area of the pDstImage. I hope the comments in the code are enough to guide you in using the kernel. I have not been able to give this a complete test, so there could be changes required. Any comments are appreciated as well.
__kernel void sobel_uchar_wlocal (__global uchar *pSrc, __global float *pDstImage, __global uint2 dimDstImage)
{
//call this kernel 1-dimensional work group size: 32x1
//calculates 32x32 region of output with 32 work items
const uint wid = get_local_id(0);
const uint wid_1 = wid+1; // corrected for the calculation step
const uint2 gid = (uint2)(get_group_id(0),get_group_id(1));
const uint localDim = get_local_size(0);
const uint2 globalTopLeft = (uint2)(localDim * gid.x, localDim * gid.y); //position in pSrc to copy from/to
//dimLocalBuff is used for the right and bottom edges of the image, where the work group may run over the border
const uint2 dimLocalBuff = (uint2)(localDim,localDim);
if(dimDstImage.x - globalTopLeft.x < dimLocalBuff.x){
dimLocalBuff.x = dimDstImage.x - globalTopLeft.x;
}
if(dimDstImage.y - globalTopLeft.y < dimLocalBuff.y){
dimLocalBuff.y = dimDstImage.y - globalTopLeft.y;
}
int i,j;
//save region of data into local memory
__local uchar srcBuff[34][34]; //34^2 uchar = 1156 bytes
for(j=-1;j<dimLocalBuff.y+1;j++){
for(i=x-1;i<dimLocalBuff.x+1;i+=localDim){
srcBuff[i+1][j+1] = pSrc[globalTopLeft.x+i][globalTopLeft.y+j];
}
}
mem_fence(CLK_LOCAL_MEM_FENCE);
//compute output and store locally
__local float dstBuff[32][32]; //32^2 float = 4096 bytes
if(wid_1 < dimLocalBuff.x){
for(i=0;i<dimLocalBuff.y;i++){
float gx = srcBuff[(wid_1-1)+ (i - 1)]-srcBuff[(wid_1-1)+ (i + 1)]+2*(srcBuff[wid_1+ (i-1)]-srcBuff[wid_1+ (i+1)])+srcBuff[(wid_1+1)+ (i - 1)]-srcBuff[(wid_1+1)+ (i + 1)];
float gy = srcBuff[(wid_1-1)+ (i - 1)]-srcBuff[(wid_1+1)+ (i - 1)]+2*(srcBuff[(wid_1-1)+ (i)]-srcBuff[(wid_1+1)+ (i)])+srcBuff[(wid_1-1)+ (i + 1)]-srcBuff[(wid_1+1)+ (i + 1)];
dstBuff[wid][i] = gx*gx + gy*gy;
}
}
mem_fence(CLK_LOCAL_MEM_FENCE);
//copy results to output
for(j=0;j<dimLocalBuff.y;j++){
for(i=0;i<dimLocalBuff.x;i+=localDim){
srcBuff[i][j] = pSrc[globalTopLeft.x+i][globalTopLeft.y+j];
}
}
}

Using loaded .raw image data as a IDirect3DTexture9 texture in DirectX9?

Im trying to make use of a simple .raw loader as an easy way to load images into a program to be used as textures by DirectX9.
I have a problem in that the D3DX functions are not available to me at all, nor can i find them anywhere. I have constructed my own matrix routines fine, but can't use the D3DX Texture file function without some pointers.
I've done my homework, so i'm thinking what i need is to use the CreateTexture function and some code to marry my unsigned char image with IDirect3DTexture9 *DXTexture.
IDirect3DTexture9 *DXTexture;
unsigned char texture;
loadRawImage(&texture, "tex", 128, 128);
g_pD3DDevice->CreateTexture(128,128,0,D3DUSAGE_DYNAMIC,D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT, &DXTexture,NULL);
//code required here to marry my unsigned char image with DXTexture
g_pD3DDevice->SetTexture(0, texture);
I've seen this page, looks sort of like what i need..
http://www.gamedev.net/topic/567044-problem-loading-image-data-into-idirect3dtexture9/
IDirect3DTexture9* tempTexture = 0;
HRESULT hr = device->CreateTexture(this->width,this,>height,0,D3DUSAGE_DYNAMIC,
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,&tempTexture,0);
//assignment pointer
D3DCOLOR *Ptr;
unsigned char *tempPtr = 0; // increment pointer
int count = 0; //index into color data
//lock texture and get ptr
D3DLOCKED_RECT rect;
hr = tempTexture->LockRect(0,&rect,0,D3DLOCK_DISCARD);
tempPtr = (unsigned char*)rect.pBits; // assign to unsigned char
// pointer to make pointer arithmetic
// smooth
for(unsigned int i = 0; i < this->height; i++)
{
tempPtr += rect.Pitch; //move to next line in texture
Ptr = (D3DCOLOR*)tempPtr;
for(unsigned int j = 0; j < this->width; j++)
{
Ptr[j] = D3DCOLOR_XRGB(this->imageData[count++],
this->imageData[count++],
this->imageData[count++]);
}
}
tempTexture->UnlockRect(0);
Any pointers would be appreciated. This is for a small demo so code is being kept down to a minimum.
EDIT to respond to drop
Basically my question is how can I use the loaded .raw image data as a DirectX9 texture? I know there must be some internal byte format in which IDirectTexture9 textures are arranged, I just need some pointers on how to convert my data to this format.This is without using D3DX functions.
Have a try using below approach
D3DLOCKED_RECT rect;
ppTexture->LockRect( 0, &rect, 0, D3DLOCK_DISCARD );
unsigned char* dest = static_cast<unsigned char*>(rect.pBits);
memcpy(dest, &pBitmapData[0], sizeof(unsigned char) * biWidth * biHeight * 4);
ppTexture->UnlockRect(0);

How to copy frame data from FFmpegSource2 (FFMS2) FFMS_Frame struct to OpenCV Mat?

I'm trying to read video file using FFmpegSource2 (FFMS2) and then process frames using OpenCV. What is the proper and efficient way to copy frame data from a FFMS_Frame struct returned by FFMS_GetFrame function to an OpenCV Mat?
Thank you very much in advance.
For now I am using the following procedure which works for the BGR color format.
Step 1. I use FFMS_SetOutputFormatV2 and FFMS_GetPixFmt( "bgra" ) to set output pixel format of FFMS to BGR.
int anPixFmts[2];
anPixFmts[0] = FFMS_GetPixFmt( "bgra" );
anPixFmts[1] = -1;
if( FFMS_SetOutputFormatV2( pstFfmsVidSrc, anPixFmts
, pstFfmsFrameProps->EncodedWidth, pstFfmsFrameProps->EncodedHeight
, FFMS_RESIZER_BICUBIC, &stFfmsErrInfo ) )
{
// handle error
}
Step 2. Read the desired frame using FFMS_GetFrame.
int nCurFrameNum = 5;
const FFMS_Frame *pstCurFfmsFrame = FFMS_GetFrame( pstFfmsVidSrc, nCurFrameNum, &stFfmsErrInfo );
Step 3. Copy data from pstCurFfmsFrame to OpenCV Mat, oMatA:
Mat oMatA;
oMatA = Mat::zeros( pstCurFfmsFrame->EncodedHeight, pstCurFfmsFrame->EncodedWidth, CV_8UC3 );
int nDi = 0;
for( int nRi = 0; nRi < oMatA.rows; nRi++ )
{
for( int nCi = 0; nCi < oMatA.cols; nCi++ )
{
oMatA.data[oMatA.step[0] * nRi + oMatA.step[1] * nCi + 0] = pstCurFfmsFrame->Data[0][nDi++]; // B
oMatA.data[oMatA.step[0] * nRi + oMatA.step[1] * nCi + 1] = pstCurFfmsFrame->Data[0][nDi++]; // G
oMatA.data[oMatA.step[0] * nRi + oMatA.step[1] * nCi + 2] = pstCurFfmsFrame->Data[0][nDi++]; // R
nDi++;
}
}
This code has to be changed to support other color formats (e.g Planar format like YV12 uses more than one plane of pstCurFfmsFrame->Data). May be someone could provide a full function to support most of the color formats and an efficient way to copy data from pstCurFfmsFrame->Data to OpenCV Mat.

OpenCV C++: how access pixel value CV_32F through uchar data pointer

Briefly, I would like to know if it is possible to directly access pixel value
of a CV_32F Mat, through Mat member "uchar* data".
I can do it with no problem if Mat is CV_8U, for example:
// a matrix 5 columns and 6 rows, values in [0,255], all elements initialised at 12
cv:Mat A;
A.create(5,6, CV_8UC1);
A = cv::Scalar(12);
//here I successfully access to pixel [4,5]
uchar *p = A.data;
int value = (uchar) p[4*A.step + 5];
The problem is when I try to do the same operation with the following matrix,
// a matrix 5 columns, 6 rows, values in [0.0, 1.0], all elements initialised at 1.2
cv::Mat B;
B.create(5,6, CV_32FC1);
B = cv::Scalar(1.2);
//this clearly does not work, no syntax error but erroneous value reported!
uchar *p = B.data;
float value = (float) p[4*B.step + 5];
//this works, but it is not what I want to do!
float value = B.at<float>(4,5);
Thanks a lot, Valerio
You can use ptr method which returns pointer to matrix row:
for (int y = 0; y < mat.rows; ++y)
{
float* row_ptr = mat.ptr<float>(y);
for (int x = 0; x < mat.cols; ++x)
{
float val = row_ptr[x];
}
}
You can also cast data pointer to float and use elem_step instead of step if matrix is continous:
float* ptr = (float*) mat.data;
size_t elem_step = mat.step / sizeof(float);
float val = ptr[i * elem_step + j];
Note that CV_32F means the elements are float instead of uchar. The "F" here means "float". And the "U" in CV_8U stands for unsigned integer. Maybe that's why your code doesn't give the right value. By declaring p as uchar*, p[4*B.step+5] makes p move to the fifth row and advance sizeof(uchar)*5, which tend to be wrong. You can try
float value = (float) p[4*B.step + 5*B.elemSize()]
but I'm not sure if it will work.
Here are some ways to pass the data of [i, j] to value:
value = B.at<float>(i, j)
value = B.ptr<float>(i)[j]
value = ((float*)B.data)[i*B.step+j]
The 3rd way is not recommended though, since it's easy to overflow. Besides, a 6x5 matrix should be created by B.create(6, 5, CV_32FC1), I think?

Resources