[Solved]help my code

Started by
5 comments, last by Great_White 15 years, 5 months ago
Hi guys, I'm trying to compute average color values of an grayscale image blocks. My grayscale image is divided into 64 blocks(think of it like placing a 8x8 grid on the image, hence each block size is image width/8 and image height/8. Here is my source code,


static void averageColorOf8x8_Blocks(unsigned char* img, int width, int height, long avgc[8][8]) {
	
	// validate arguments
	assert(img);
	assert(width);
	assert(height);

	// calculate block size(block width x block height)
	int blck_w= width/8, blck_h=height/8;

	// compute average of each block(to get 64 color values)
	for(int y=0;y<height;y+=blck_h) { // for each vertical block
		for(int x=0;x<width;x+=blck_w) { // for each horizontal block
			for(int z=0;z<blck_h;++z) {  // for each block entry
				for(int w=0;w<blck_w;++w) {
					avgc[y/blck_h][x/blck_w] += (long)img[(y+z)*width +x+w ];
				}
			}

			avgc[y/blck_h][x/blck_w] *= 1/(blck_w*blck_h); // average
		}
	}
}




But when I try it on some images that are not multiple of 8, it crashes. Can somebody explain me what I'm doing wrong ? [Edited by - Great_White on November 21, 2008 1:17:51 AM]
"A human being is a part of a whole, called by us,universe, a part limited in time and space. He experiences himself, his thoughts and feelings as something separated from the rest... a kind of optical delusion of his consciousness. This delusion is a kind of prison for us, restricting us to our personal desires and to affection for a few persons nearest to us. Our task must be to free ourselves from this prison by widening our circle of compassion to embrace all living creatures and the whole of nature in its beauty."A. Einstein
Advertisement
This won't break on every size that's not a multiple of 8, but it will on many of them, and it'll go into infinite-loop world on sizes < 8. For instance all sizes 8-16 will work just fine. Anyway let's examine why.

Let's go through a test situation. Imagine a simple greyscale image that is 17x17. You get your blck_w and blck_h, and naturally they are both "2" (as 17/8 = 2.125 or something... in integer world that's 2).

Alright great... recap the vars:
width = 17 height = 17 blck_w = 2 blck_h = 2

Now let's look at the for loops. If you were to set a breakpoint in here, you would end up starting your "y" loop, "x" loop, "z" loop, and "w" loop, you would eventually make it through the "z" and "w" loops successfully. You would start the next "x" loop, with x = 2 now. This will go on until x == 14. We go through the "z" and "w" loops like usual, but let's zoom in and see what happens next.

The for loop says "Well, 'x' == 14. I need to add 'blck_w' to it. That's 2. Cool, so now 'x' == 16. Is that less than 'width'? 'width' is 17... sooo... yup 16 is certainly less than 17, let's move on."

And the "z" loop and "w" loop start. Since the "z" loop and "w" loop both iterate "blck_w" times, you are going past your image width and height of 17, as if it was 18x18. This is why it crashes.

Solution?

Decide what to do with the "extra" pixels when it's not evenly divisible by 8. Throw them away, or determine a way to only include what's there.

Cheers
-Scott

ok discarding them is a good idea. How can I do this? BTW, my logic is correct right? I trying to copy calculated average block color values to a 8x8 array.
"A human being is a part of a whole, called by us,universe, a part limited in time and space. He experiences himself, his thoughts and feelings as something separated from the rest... a kind of optical delusion of his consciousness. This delusion is a kind of prison for us, restricting us to our personal desires and to affection for a few persons nearest to us. Our task must be to free ourselves from this prison by widening our circle of compassion to embrace all living creatures and the whole of nature in its beauty."A. Einstein
Here's a hint: Try iterating through each pixel of the image and finding out which cell of avgc it should go in. Also, it may be helpful to know that the average is the sum of all elements then divided by how many elements possible.


Does this give you any ideas?
a code sample will be better for me to understand
"A human being is a part of a whole, called by us,universe, a part limited in time and space. He experiences himself, his thoughts and feelings as something separated from the rest... a kind of optical delusion of his consciousness. This delusion is a kind of prison for us, restricting us to our personal desires and to affection for a few persons nearest to us. Our task must be to free ourselves from this prison by widening our circle of compassion to embrace all living creatures and the whole of nature in its beauty."A. Einstein
Oh, wait. What's this in my back pocket? Some sample code?
</inside_joke>

static void averageColorOf8x8_Blocks(unsigned char* img, int width, int height, /* unsigned */ long avgc[8][8]) {	assert( width > 8 );	assert( height > 8 );		int block_w = width / 8;  	int block_h = height / 8;		// I'll be assuming that argvc is initialized to 0		// Calculate the sum:	int x, y;	for ( y = 0; y < height; ++y ) // For each row		for ( x = 0; x < width; ++x ) // For each column:			avgc[y*8/height][x*8/width] += img[ width * y + x ];		// y * 8 / height is equivalent to y / (height / 8) is equivalent to y / block_h. 	// The difference is, is that you're operating on integer operations.	// Therefore, if the height is 15 (making block_h = 15 / 8 = 1) 	// and y was 14, you'd be accessing avgc[15], which is not cool.	// Then calculate the average:	int k = block_w * block_h;	for ( y = 0; y < 8; ++y )		for ( x = 0; x < 8; ++x )			avgc[y][x] /= k;}



[Edited by - _fastcall on November 19, 2008 9:31:33 PM]
Thanks for the sample code. But it does not give the correct results, I checked with Matlab. I think my for logic is not correct.
"A human being is a part of a whole, called by us,universe, a part limited in time and space. He experiences himself, his thoughts and feelings as something separated from the rest... a kind of optical delusion of his consciousness. This delusion is a kind of prison for us, restricting us to our personal desires and to affection for a few persons nearest to us. Our task must be to free ourselves from this prison by widening our circle of compassion to embrace all living creatures and the whole of nature in its beauty."A. Einstein

This topic is closed to new replies.

Advertisement