No copy for complex images ?

No copy for complex images ?

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...)

10 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

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

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.

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?

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.

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

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?

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);
}

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

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

Leave a Comment

Please sign in to add a comment. Not a member? Join today