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

Pixel variance between IPP7 vs IPP9 using ippiCopy

Wan__John
Beginner
641 Views

Hi,

As titled, I'm currently having trouble obtaining the equivalent pixels value between IPP7 and IPP9 when I'm trying to copy a 8-bit image using ippiCopy. To confirm the variance, I've print all of the pixel values of both images into CSV format individually and compare both of them using winMerge, the variance were off by somewhat a large amount (between 1 to 60). Due to that, the generated result after different types of image processing method were affected as well. Were this suppose to be a bug or intentional?

Code Snippet:
IppStatus status = ippiCopy_8u_C1R(src, srcPitch, dst, dstPitch, srcRoiSize);

Update 2.5: 
Found the culprit, it was caused by ippiMalloc_<mod>, apparently the returned pStepBytes was not as same compared to Ipp7's even-though both heights and widths are the same. A bug perhaps?

Please advise.

Thanks,

 

0 Kudos
11 Replies
Ying_H_Intel
Employee
641 Views

Hi John,

It is unknown problem.  You mentioned,  ippiMalloc_<mod>,  and ippiCopy_8u_C1R, how do you call them together.  Could you please show more parameters about your call? or one small test case should be help.

Best Regards,
Ying

 

0 Kudos
Wan__John
Beginner
641 Views

Hi Ying,

Thank you for the prompt response. As mentioned in my updates, the problem no longer reside on ippiCopy_8u_C1R but actually on ippiMalloc_<mod>, although there are some other functions that still causes pixel variances, but one problem at a time.

Here's a small example:
int src_tempPitch = 0;
Ipp8u* src_temp = ippiMalloc_8u_C1(1089, 1089, &src_tempPitch);

When IPP7 ran the code above, the src_tempPitch I'll be getting will be 1120, where as IPP9 returned me 1152 instead. Was it intended?

Thanks.

0 Kudos
Igor_A_Intel
Employee
641 Views

Hi John,

Default alignment has changed to 64 bytes as IPP supports AVX-512 now. This approach guarantees aligned data load for any image row.

regards, Igor

 

0 Kudos
Wan__John
Beginner
641 Views

Hi Igor,

That do explains why I'm getting different stepBytes. But unfortunately some of the results generated from IPP9 program are not equivalent with IPP7's due to ippiMalloc_<mod>. Is there any way to change the default alignment  as same as the one that the IPP7 is using?

Thanks.

0 Kudos
Ying_H_Intel
Employee
641 Views

Hi John,

the ippiMalloc can help aligned memory with 32 bytes(8.0) or 64bytes  (9.0),  but it is not required, so if you'd make sure the src_tempPitch  be 1120 ,  you may try Malloc(1089*1120) or ippsMalloc_8u(1089*1120) and set them manually.

On the other hand, when you get such Pitch, there are padding at the end of row. you may take care of them and keep the result correct.

For example,

int src_tempPitch = 0;
Ipp8u* src_temp = ippiMalloc_8u_C1(1089, 1089, &src_tempPitch);
Ipp8u* dst = Malloc(1089*1120);
int distPitch = 1120;
IppStatus status = ippiCopy_8u_C1R(src, src_tempPitch, dst, dstPitch, srcRoiSize);

Best Regards,
Ying

0 Kudos
Wan__John
Beginner
641 Views

Hi Ying,

First and foremost, thank you for the prompt response. Could you further elaborate on the examples you have given? Unfortunately the srcPitch will not be affix on 1120, as my program support wide variety size of images. In addition, what needs to be done if I want to apply the same method on 8-bit to 32-bit conversion?

Here's some examples:
CASE A:

//srcPitch = 1120
int srcWidth = 1089;
int srcHeight = 1089;

int src_tempPitch = 0;
Ipp8u* src_temp = ippiMalloc_8u_C1(srcWidth, srcHeight, &src_tempPitch);  // Returned 1152 instead of 1120
IppStatus status =  status = ippiCopy_8u_C1R(src, srcPitch, src_temp, src_tempPitch, srcRoiSize); 

CASE B:

//srcPitch = 1120
int srcWidth = 1089;
int srcHeight = 1089;
int src32Pitch = 0;

Ipp32f* src32f = ::ippiMalloc_32f_C1(srcWidth, srcHeight, &src32fPitch); // Returned 4412 instead of 4384
IppiSize const srcRoiSize = {srcWidth, srcHeight};
IppStatus status = ippiConvert_8u32f_C1R(src, srcPitch, src32f, src32fPitch, srcRoiSize);

 

0 Kudos
Ying_H_Intel
Employee
641 Views

Hi John, 

I attach one sample, which show the  result like below. 

ippIP AVX2 (l9) 7.1.1 (r37466) 7.1.1.37466
src_tempPitch : 64
original src :
1 ; 2 ; 127 ; 4 ; 5 ; 0 ;
 ippiCopy_8u_C1R status ippStsNoErr: No errors.:
1 ; 2 ; 127 ; 75 ; 0 ; 0 ;
 ippiCopy_8u_C1R correct result should be :
1 ; 2 ; 127 ; 4 ; 5 ; 0 ;
Press any key to continue . . .

 

ippIP AVX2 (l9) 2017.0.1 (r53196) 2017.0.1.53196
src_tempPitch : 64
original src :
1 ; 2 ; 127 ; 4 ; 5 ; 0 ;
 ippiCopy_8u_C1R status ippStsNoErr: No errors.:
1 ; 2 ; 127 ; 0 ; 0 ; 0 ;
 ippiCopy_8u_C1R correct result should be :
1 ; 2 ; 127 ; 4 ; 5 ; 0 ;
Press any key to continue . . .

Actually, whatever of src_tempPitch is or ippiMalloc aligned with 32 or 64, you may take care of the result image based on it. for example, when your read image, you should drop the padding pixel, like 

printf("\n ippiCopy_8u_C1R correct result should be :\n");
	for(int i = 0; i < 2; i++) 
		for(int j = 0; j < 3; j++) 
		printf("%hd ; ", src_temp[i*src_tempPitch + j]);

Same as 32f type. 

#include "stdafx.h"
#include "ipp.h"

//#define IPP_90

int _tmain(int argc, _TCHAR* argv[])
{
	const IppLibraryVersion* lib = ippiGetLibVersion();
	printf("%s %s %d.%d.%d.%d\n",lib->Name, lib->Version,lib->major,
	lib->minor, lib->majorBuild, lib->build);

	Ipp8u src[2*3] = {1,2,127,4,5,0};
	
#ifdef IPP_70	
	
	int srcWidth = 3;
    int srcHeight = 2;

int src_tempPitch = 0;
Ipp8u* src_temp = ippiMalloc_8u_C1(srcWidth, srcHeight, &src_tempPitch);  // Returned 1152 instead of 1120
IppStatus status =   ippiCopy_8u_C1R(src, srcPitch, src_temp, src_tempPitch, srcRoiSize); 


#else
	int srcWidth = 3;
    int srcHeight = 2;
	IppiSize srcRoiSize={srcWidth,srcHeight};
	int srcPitch = 3; 
int src_tempPitch = 0;
Ipp8u* src_temp = ippiMalloc_8u_C1(srcWidth, srcHeight, &src_tempPitch);  // Returned 1152 instead of 1120
printf("src_tempPitch : %d\n", src_tempPitch ); 
IppStatus  status = ippiCopy_8u_C1R(src, srcPitch, src_temp, src_tempPitch, srcRoiSize); 

#endif
    printf("original src :\n"); 
	for(int i = 0; i < 6; i++) printf("%hd ; ", src);

	printf("\n ippiCopy_8u_C1R status %s:\n", ippGetStatusString(status));
	for(int i = 0; i < 6; i++) printf("%hd ; ", src_temp);

	
		printf("\n ippiCopy_8u_C1R correct result should be :\n");
	for(int i = 0; i < 2; i++) 
		for(int j = 0; j < 3; j++) 
		printf("%hd ; ", src_temp[i*src_tempPitch + j]);

	printf("\n");

}

Best Regards,

Ying

0 Kudos
Wan__John
Beginner
641 Views

Hi Ying,

Thank you, that really helps a lot. 
Just another question, does the ippiColorToGray function respecting the pitch of the image? Because somehow pixels variance occurs after that function between IPP7 and IPP9. Previously I tried ippiRGBToGray_<mod> instead but variance was even worse.

Here's a snippet: 

int srcWidth = 1089;
int srcHeight = 1089;
int dstWidth = 1089;
int dstHeight = 1089;

int dst8uPitch = 0;
Ipp8u* dst8uC3 = ::ippiMalloc_8u_C3(srcWidth , srcHeight , &dst8uPitch);
::IppiSize const srcRoiSize = { srcWidth , srcHeight };
::IppiSize const dstRoiSize = { dstWidth , dstHeight };
::IppiRect srcRect = { 0, 0, srcWidth , srcHeight };
Ipp32f coeffs[3] = { 0.2126f, 0.7152f, 0.0722f };  //Luminance

status = ::ippiCFAToRGB_8u_C1C3R(src, srcRect, srcRoiSize, srcPitch, dst8uC3, dst8uPitch, ippiBayerRGGB, 0);
status = ::ippiColorToGray_8u_C3C1R(dst8uC3, dst8uPitch, dst, dstPitch, srcRoiSize, coeffs); // Variance happens here

Again, you're help is greatly appreciated.

Thanks

0 Kudos
Ying_H_Intel
Employee
641 Views

Hi John,

Yes, whatever aligned, all of IPP functions will respect to the stepBytes, (that is why the parameter was designed here.)  You mentioned that "somehow pixels variance occurs ",   if  default assume that ippiCFAToRBG and ippiColorToGray haven't bug,  then it should be get same result in IPP 7.0 and 2017. .

and read the dst data based on dstPitchs.

 printf("\n Dst[2*3] result should be :\n");
 for(int i = 0; i < dstHeight ; i++)
  for(int j = 0; j < dstWidth; j++)
  printf("%hd ; ", src_temp[i*dstPitch + j]);

I test the piece of the code  you attached with 2017 update 1, Please tell if any change in 7.1.

best Regards,
Ying

ippIP AVX2 (l9) 2017.0.1 (r53196) 2017.0.1.53196
src_tempPitch : 64
original src :
1 ; 2 ; 127 ; 4 ; 5 ; 0 ;
 ippiCopy_8u_C1R status ippStsNoErr: No errors.:
1 ; 2 ; 127 ; 0 ; 0 ; 0 ;
 ippiCopy_8u_C1R correct result should be :
1 ; 2 ; 127 ; 4 ; 5 ; 0 ;
 Dst[2*3] result should be :
1 ; 2 ; 127 ; 0 ; 0 ; 0 ;
Press any key to continue . . .

 

#include "stdafx.h"
#include "ipp.h"

//#define IPP_90

int _tmain(int argc, _TCHAR* argv[])
{
 const IppLibraryVersion* lib = ippiGetLibVersion();
 printf("%s %s %d.%d.%d.%d\n",lib->Name, lib->Version,lib->major,
 lib->minor, lib->majorBuild, lib->build);

 Ipp8u src[2*3] = {1,2,127,4,5,0};
 
#ifdef IPP_70 
 
 int srcWidth = 3;
    int srcHeight = 2;

int src_tempPitch = 0;
Ipp8u* src_temp = ippiMalloc_8u_C1(srcWidth, srcHeight, &src_tempPitch);  // Returned 1152 instead of 1120
IppStatus status =   ippiCopy_8u_C1R(src, srcPitch, src_temp, src_tempPitch, srcRoiSize); 


#else
 int srcWidth = 3;
    int srcHeight = 2;
 IppiSize srcRoiSize={srcWidth,srcHeight};
 int srcPitch = 3; 
int src_tempPitch = 0;
Ipp8u* src_temp = ippiMalloc_8u_C1(srcWidth, srcHeight, &src_tempPitch);  // Returned 1152 instead of 1120
printf("src_tempPitch : %d\n", src_tempPitch ); 
IppStatus  status1 = ippiCopy_8u_C1R(src, srcPitch, src_temp, src_tempPitch, srcRoiSize); 

int dstWidth = 3;
int dstHeight = 2;
int dstPitch = dstWidth *sizeof(Ipp8u);
Ipp8u dst[2*3];
int dst8uPitch = 0;
Ipp8u* dst8uC3 = ::ippiMalloc_8u_C3(srcWidth , srcHeight , &dst8uPitch);
//IppiSize const srcRoiSize = { srcWidth , srcHeight };
IppiSize const dstRoiSize = { dstWidth , dstHeight };
IppiRect srcRect = { 0, 0, srcWidth , srcHeight };
Ipp32f coeffs[3] = { 0.2126f, 0.7152f, 0.0722f };  //Luminance

IppStatus  status2 = ippiCFAToRGB_8u_C1C3R(src, srcRect, srcRoiSize, srcPitch, dst8uC3, dst8uPitch, ippiBayerRGGB, 0);
IppStatus  status3 = ippiColorToGray_8u_C3C1R(dst8uC3, dst8uPitch, dst, dstPitch, srcRoiSize, coeffs);


#endif
    printf("original src :\n"); 
 for(int i = 0; i < 6; i++) printf("%hd ; ", src);

 printf("\n ippiCopy_8u_C1R status %s:\n", ippGetStatusString(status1));
 for(int i = 0; i < 6; i++) printf("%hd ; ", src_temp);

 
  printf("\n ippiCopy_8u_C1R correct result should be :\n");
 for(int i = 0; i < 2; i++) 
  for(int j = 0; j < 3; j++) 
  printf("%hd ; ", src_temp[i*src_tempPitch + j]);

   printf("\n Dst[2*3] result should be :\n");
 for(int i = 0; i < dstHeight ; i++) 
  for(int j = 0; j < dstWidth; j++) 
  printf("%hd ; ", src_temp[i*dstPitch + j]);

 printf("\n");

}

 

 

0 Kudos
Wan__John
Beginner
641 Views

Hi Ying,

I can confirmed the variance doesn't occurs with the sample array you've given. But it does happens on the 1089 x 1089 images I'm currently processing.

The function below were used to generate CSV files containing the images pixels for comparison:

static void debugCSV(unsigned char const* const src, IppiSize srcRoiSize, const char* savePath, int srcPitch)
{
	std::ofstream file(savePath, std::ios_base::out | std::ios_base::app);
	for (int i = 0; i< srcRoiSize.height; ++i)
		for (int j = 0; j< srcRoiSize.width; ++j)
		{
			file << j << "," << i << "," << static_cast<int>(src[i*srcPitch + j]) << std::endl;
		}
}

Thanks.

0 Kudos
Ying_H_Intel
Employee
641 Views

Hi John,

Could you send the CSV or the jpg image to us to test?

Best Regards,

Ying

0 Kudos
Reply