Help with library function

Write your question here.
I am handling DCM (dicom) images. I want to compare different images by their pixel values. I have found function which function which return pixel values of the image BUT I would like to allow a little bit tolerance for that comparison. For example 10 % difference could be OK. Now I can just check is it completely same number or not. I cannot just use < > operators due to pointer return value.
I am using this function:

const void* DicomImage::getOutputData
(
const int
bits = 0,


const unsigned long
frame = 0,


const int
planar = 0

)
render pixel data and return pointer to internal memory buffer.
apply VOI/PLUT transformation and (visible) overlay planes. internal memory buffer will be delete for the next getBitmap/Output operation. output data is always padded to 8, 16, 32, ... bits (bits allocated). Supported output color models: Monochrome 2 for monochrome images and RGB (or YCbCr_Full if flag CIF_KeepYCbCrColorModel is set) for color images. The rendered pixel data is always unsigned.

Parameters:

bits

number of bits per sample used to render the pixel data (image depth, 1..MAX_BITS, 0 means 'bits stored' in the image) (MI_PastelColor = -1 for true color pastel mode, EXPERIMENTAL)
frame
number of frame to be rendered (0..n-1)

planar

0 = color-by-pixel (R1G1B1...R2G2B2...R3G3B3...), 1 = color-by-plane (R1R2R3...G1G2G3...B1B2B3...) (only applicable to multi-planar/color images, otherwise ignored)
Returns
pointer to internal memory buffer containing rendered pixel data (if successful, NULL otherwise)

Thank you for your help, I really appreciate your help! :)
1
2
3
4
5
6
7
8
9
10
11
   // we get pixels values of current file
            Uint8 *pdata = (Uint8 *)(image.getOutputData(8));

            // we will count difference in pixels
            int d = 0;
            // so cycl for all pixel values
			for (int j = 0; j < fsize; j++) {
// and if pixel of current and first file are not equal we increment d variable
				
				
				if (fdata[j] != pdata[j]) d++;


I would like to write something like:
if (abs((abs(fdata[j]) - abs(pdata[j])))>0.1*abs(pdata[j])) d++;
But it fails. Thank you!
Last edited on
So first, let me explain that the type of your data is, according to your types, an array of Uint8 values. The U here stands for unsigned, meaning the value can only be 0-255, and can't be negative in the first place. Therefore, taking the absolute value of an unsigned number doesn't do anything. And when you subtract unsigned types, the values wrap around. (e.g. 100u - 101u = 255u) This is probably what's causing part of the strange or erroneous behavior.

I always get confused by percent difference vs percent change, and things get hazy once you get close to 0, but I think in this situation both are erroneous to use.

For example, let's say the Red component of the first image's pixel is 1, and the Red component of the second image's pixel is 2. This should totally be within the tolerance you're looking for... right?

But... the percent difference between 1 and 2 is 66.7%.
And the percent change from 1 to 2 is a 100% increase.
Neither of these make sense in the context of you comparing the images!

What I think you're actually trying to do is see if the difference between two values is within 10% of the possible range that those values could be. I'm not sure what the best way to phrase that is.

The range of your data is 0 to 255, inclusive, if we're working with Uint8. So, 10% of 255 is 25.5. If we round that to 26, that means your two pieces of data should be within 26 values to be considered "close enough" to each other.

Something like this. Notice we first convert the Uint8 data to a wider, signed type in order to be able to take the difference correctly. If you cannot cast, you must first find which value is bigger, and subtract the smaller value.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// Example program
#include <iostream>
#include <algorithm>
#include <string>

#include <cstdint>

using Uint8 = std::uint8_t;
const Uint8 RGB_Max = 255;

bool close_enough(Uint8 a, Uint8 b, double percent)
{
   return abs(static_cast<int>(a) - static_cast<int>(b)) < static_cast<int>(percent * RGB_Max + 0.5);
}

bool close_enough_without_cast(Uint8 a, Uint8 b, double percent)
{
   // http://www.cplusplus.com/reference/algorithm/max/
   const Uint8& max_comp = std::max(a, b);
   const Uint8& min_comp = std::min(a, b);
   return max_comp - min_comp < static_cast<Uint8>(percent * RGB_Max + 0.5);
}


int main()
{
    double percent = 0.10;
    
    Uint8 fdata[] = {100, 200, 230, 50, 0, 255};
    Uint8 pdata[] = {150, 190, 200, 70, 2, 250};
    
    for (int j = 0; j < 6; j++)
    {
        Uint8 a = fdata[j];
        Uint8 b = pdata[j];
        
        // Converting to (int) just to print it out correctly
        std::cout << (int)a << " " << (int)b << " -> ";
        if (close_enough_without_cast(a, b, percent))
        {
             std::cout << " ... okay" << std::endl;
        }
        else
        {
            std::cout << " ... not close enough!" << std::endl;
        }
    }

}


Output:
1
2
3
4
5
6
7
Success	#stdin #stdout 0s 4452KB
100 150 ->  ... not close enough!
200 190 ->  ... okay
230 200 ->  ... not close enough!
50 70 ->  ... okay
0 2 ->  ... okay
255 250 ->  ... okay


____________________________________________________

Note that the differences in the numerical value of a pixel is different than what our eyes actually perceive. The difference in perception between RGB(0, 0, 0) and RGB(10, 10, 10) is actually much greater than the difference between RGB(240, 240, 240) and RGB(250, 250, 250). Changes in dark values matter more than changes in light values. And once you add in color, things get even more complicated. Since these are DICOM files, I assume this is some medical-related situation you're in. To be the most accurate, you must account for the perceptual differences*.

Read about the gamma transfer function and search more stuff about it if you're interested.
https://en.wikipedia.org/wiki/SRGB

*I'm just talking about in general though. I don't actually know what the current medical standards are, DICOM or not, when dealing with RGB colors or different color spaces. Seek a professional for that :p)

Last edited on
Thank you very much for your answer, I'll try that. Your explanation was very clear.
Topic archived. No new replies allowed.