Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.

No copy for complex images ?

Intel_C_Intel
Employee
623 Views
In the IPP libraries, there are no "ippiCopy_32fc" routines to copy a (part of a) complex-valued image into another.
Is there a reason for this ? (I programmed one in order to circumvent this...)
0 Kudos
9 Replies
Ying_S_Intel
Employee
623 Views
Dear Customer,
If you think this is an important feature for your development, please submit a detailed feature requestinto Intel Premier Support so our development team will review it in the next product definition cycle and will decide if or not it is needed to implement.

Thanks,
Ying
Intel IPP
0 Kudos
Amanda_S_Intel
Employee
623 Views
Hi,
You don't need a special copy function for complex images;just treat the image as a non-complex image with double the size.
Regards,
--Amanda S.
Intel Corp.
0 Kudos
thijse
Beginner
623 Views

I am having the same problems with complexfunctions. A lot of (basic) functions (like set, copy, etc) do not have complex counter parts. If I treat the image as twice the size, should I make it twice the width or twice the height? Could you give a basic example setting, say, a 100x100 image to a value of Re=1.0, Im = 0.0?

I am planning to perform a 2D convolutionin Fourier space using IPP. I have seen the 2D convolution routines in de IPPI manual, but they seem in to work in the spatial domain and should thus be much slower. Is this true?

0 Kudos
thijse
Beginner
623 Views

In general, could one adress the real and imaginary parts as different channels? Such as:

const int Ipp32fSize = sizeof( Ipp32f );
IppiSize srcSize = {100, 100};

// Create a single channel, complex image...
Ipp32fc* srcImage= ( Ipp32fc * )ippiMalloc_32fc_C1( srcSize.width, srcSize.height, &stepBytes );

// ...but adress as dual channel, real image:

// Initialize real part (1st channel) to 1.0f
ippiSet_32f_C1CR( 1.0f, srcImage, srcSize.width * Ipp32fSize, srcSize );

// Initialize imaginary part (2st channel) to 0.0f
ippiSet_32f_C2CR( 0.0f, srcImage, srcSize.width * Ipp32fSize, srcSize );

ippiFree( srcImage );

Please excuse me if I am asking things that are in the manual but I overlooked.

0 Kudos
Vladimir_Dudnik
Employee
623 Views

Hello,

there is comment from our expert:

There is no direct support for complex images, so using of ippiSet for 32f complex data is too tricky:

For his example:

IPPAPI ( IppStatus, ippiSet_32f_C4R,

( const Ipp32f value[4], Ipp32f* pDst, int dstStep,

IppiSize roiSize ))

where Ipp32f value[4] = {1.0, 0.0, 1.0, 0.0};

IppiSize roiSize = {50, 100}; // if complex points were mentioned he should divide by 2, 100/2 = 50; height is not touched.

Int dstStep = 400; // 50 complex numbers in row, each consists of two 4-bytes floats.

2D convolution function (ippiConvFull/Valid) is highly optimized and uses direct calculations in boundary cases only (when one of the images is too small, or dst image is too small and algorithm based on FFT is not effective). In all other cases convolution is based on convolution theorem algorithm.

Regards,
Vladimir

0 Kudos
thijse
Beginner
623 Views

Thanks,

Because we want to manipulate our convolution filters in Fourier spacewe have decided to use the FFTFwd and FFTInv algorithms and do our convolution using MulPack, instead of using ConvFull.

However, this brought me to the next problem: I would like to individually manipulate the complex values in the Complex Packed Fourier image, but I found it hard toconstruct an elegant (or efficient) algorithm to find the real and imaginary values corresponding
totheir position (x,y) in the original image,that will work for RCPack2D storage images with both odd and even rows and columns. Could you perhaps provide (C-code) for such an algorithm?

Alternatively, I could use PackToCplxExtend to create a "normal" complex image and manipulate those values, but I could not find a reverse function, (CplxToPackToCompact ?). Does such an function exist?

0 Kudos
thijse
Beginner
623 Views

This is the function that I am now trying. Is this a correct mapping of Ipp32fc A(x,y) to an RCPack2D Storage image?

( IppImage src is an object that wraps an Ipp32f image.
src.pixel(x,y) returns the value of pixel(x,y), etc. )

Ipp32fc CSquareFilter::getRCPackedElement(IppImage& src,int x, int y) {

// According to Table 10-4 && 10-5 a RCPack2D stored image is transposed?

Ipp32fc value;

int EvenM = ((src.width() % 2) ==0 );
int EvenN = ((src.height() % 2) ==0 );
int Mdiv2 = src.width() / 2;
int Ndiv2 = src.height() / 2;
int RCPcolumn;
int RCProw;

if ((y==0) || (y==Ndiv2 && EvenN)) {

RCPcolumn = (y*2)-1;// is image transposed? y => column?
if (x==0) {
// A(0,0) or A(0,N/2)
RCProw = 0;
value.re = src.pixel(RCPcolumn,RCProw);
value.im = 0.0;// for A(0,0) Freq = 0 the phase is irrelevant?
} else {
RCProw = (x*2)-1;
if ((x==Mdiv2) && EvenM) {
// A(M/2,0) or A(M/2,N/2)
value.re = src.pixel(RCPcolumn,RCProw);
value.im = 0;// Im A(M/2,0) = 0 and A(M/2,N/2) = 0 for even number of rows?
} else {
// A(x,0) or A(x,N/2)
value.re = src.pixel(RCPcolumn,RCProw);
value.im = src.pixel(RCPcolumn,RCProw+1);
}
}
} else {
// A(x,y)
RCPcolumn = (y*2)-1;
RCProw = x;
value.re = src.pixel(RCPcolumn,RCProw);
value.im = src.pixel(RCPcolumn+1,RCProw);
}

return (value);
}

0 Kudos
thijse
Beginner
623 Views

To code below actually runs and seem to give results that look to me as correct a mapping of an (x,y) position in a "normal" complex image (forx= 0,...,M-1;y = 0,... N/2) onto a (RCPcolumn, RCProw)position (forRCPcolumn = 0,...,N;RCProw = 0,... M).

However, the resulting values of my routine are not as expected. Could anybody verify this routine?

void CSquareFilter::testGetRCPackedElement(int width, int height,int x, int y) {

// According to Table 10-4 && 10-5 a RCPack2D stored image is transposed.
//is this correct?


Ipp32fc value;
value.re = 0.0;
value.im = 0.0;

int EvenM = ((width % 2) ==0 );
int EvenN = ((height % 2) ==0 );
int Mdiv2 = width / 2;
int Ndiv2 = height / 2;
int RCPcolumn;
int RCProw;

if ((y==0) || (y==Ndiv2 && EvenN)) {
if (y== 0) { RCPcolumn = 0; } else {RCPcolumn = (y*2)-1; }// is image transposed? y => column?
if (x > Mdiv2) {
// This data is not present
printf("Orig x= %i, y = %i -> re: RCP Not present ", x,y);
printf("Orig x= %i, y = %i -> im: RCP Not present ", x,y);
return;
}
if (x==0) {
// A(0,0) or A(0,N/2)
RCProw = 0;
printf("Orig x= %i, y = %i -> RCP re: x= %i, y = %i ", x,y,RCPcolumn, RCProw);
printf("Orig x= %i, y = %i -> RCP im: Not present ", x,y);

return;

} else {
RCProw = (x*2)-1;
if ((x==Mdiv2) && EvenM) {
// A(M/2,0) or A(M/2,N/2)
printf("Orig x= %i, y = %i -> RCP x= %i, y = %i ", x,y,RCPcolumn, RCProw);
printf("Orig x= %i, y = %i -> RCP im: Not present ", x,y);
return;

} else {
// A(x,0) or A(x,N/2)
printf("Orig x= %i, y = %i -> RCP re: x= %i, y = %i ", x,y,RCPcolumn, RCProw);
printf("Orig x= %i, y = %i -> RCP im: x= %i, y = %i ", x,y,RCPcolumn, RCProw+1);
return;

}
}
} else {
// A(x,y)
RCPcolumn = (y*2)-1;
RCProw = x;
printf("Orig x= %i, y = %i -> RCP re: x= %i, y = %i ", x,y,RCPcolumn, RCPro w);
printf("Orig x= %i, y = %i -> RCP im: x= %i, y = %i ", x,y,RCPcolumn+1, RCProw);
return;
}
}

Calling the routine, with some "difficult" points:


int width = 10;
int height = 10;
testGetRCPackedElement(width,height,0 ,0);
testGetRCPackedElement(width,height,int (width/2) ,0);
testGetRCPackedElement(width,height,int (width/2) ,int(height/2));
testGetRCPackedElement(width,height,0 ,int(height/2));
testGetRCPackedElement(width,height,int (width-1) ,1);
testGetRCPackedElement(width,height,int (width-1) ,int((height-1)/2));
testGetRCPackedElement(width,height,int (width-1) ,int((height-0)/2));

returns:

Orig x= 0, y = 0 -> RCP re: x= 0, y = 0
Orig x= 0, y = 0 -> RCP im: Not present

Orig x= 5, y = 0 -> RCP x= 0, y = 9
Orig x= 5, y = 0 -> RCP im: Not present

Orig x= 5, y = 5 -> RCP x= 9, y = 9
Orig x= 5, y = 5 -> RCP im: Not present

Orig x= 0, y = 5 -> RCP re: x= 9, y = 0
Orig x= 0, y = 5 -> RCP im: Not present

Orig x= 9, y = 1 -> RCP re: x= 1, y = 9
Orig x= 9, y = 1 -> RCP im: x= 2, y = 9

Orig x= 9, y = 4 -> RCP re: x= 7, y = 9
Orig x= 9, y = 4 -> RCP im: x= 8, y = 9

Orig x= 9, y = 5 -> re: RCP Not present
Orig x= 9, y = 5 -> im: RCP Not present

0 Kudos
Intel_C_Intel
Employee
623 Views

Hi,

For simple functions (copy, arithm etc) when there is no versions for complex data but there exist function for real data you can use ROI with doubles width:

IppiSize roiCompl,roiReal;

roiReal.width=roiCompl.width*2;

roiReal.height=roiCompl.height;

So you can call ippiCopy_32f_C1R to copy 32fc_C1 image with roiReal and the same step (it is in bytes)

Thanks,

Alexander

0 Kudos
Reply