Loading color values from pixel array - c++

I read this tutorial http://tipsandtricks.runicsoft.com/Cpp/BitmapTutorial.html about bitmap and it really helped..I need to read color integer values from elements of pixel array. How to do that?
Ok heres the code for putting data into rgb array
BYTE* ConvertBMPToRGBBuffer ( BYTE* Buffer, int width, int height )
{
if ( ( NULL == Buffer ) || ( width == 0 ) || ( height == 0 ) )
return NULL;
// find the number of padding bytes
int padding = 0;
int scanlinebytes = width * 3;
while ( ( scanlinebytes + padding ) % 4 != 0 ) // DWORD = 4 bytes
padding++;
// get the padded scanline width
int psw = scanlinebytes + padding;
// create new buffer
BYTE* newbuf = new BYTE[width*height*3];
// now we loop trough all bytes of the original buffer,
// swap the R and B bytes and the scanlines
long bufpos = 0;
long newpos = 0;
for ( int y = 0; y < height; y++ )
for ( int x = 0; x < 3 * width; x+=3 )
{
newpos = y * 3 * width + x;
bufpos = ( height - y - 1 ) * psw + x;
newbuf[newpos] = Buffer[bufpos + 2];
newbuf[newpos + 1] = Buffer[bufpos+1];
newbuf[newpos + 2] = Buffer[bufpos];
}
return newbuf;
}

It looks like your image is in RGB interleaved format. To get a pixel at (x,y), simply index the array at that location. It would be easiest if your buffer pointed to a structure type. Something like:
typedef struct RGBPixel {
BYTE red;
BYTE green;
BYTE blue;
} RGBPixel;
Then you could do something like this:
RGBPixel* pixels = (RGBPixel*)newbuf;
To get a pixel at (x,y), you'd do this:
RGBPixel aPixel = pixels [ y * width + x ];

Related

How to set a value at memory offset from a const void pointer?

I have a pointer returned from a function
rs2::video_frame frame = frames.get_color_frame();
const void* data = frame.get_data();
I know that this pointer is an array of RGB values (i.e. 3 chars) of size frame.get_data_size().
How can I modify certain pixel colors given that
int bpp = frame.get_bytes_per_pixel();
int width = frame.get_width();
int height = frame.get_height();
int offset = (y * width * bpp) + (x * bpp);
int r = offset;
int g = offset + 1;
int b = offset + 2;
// ?data[r] = newRed;
// ?data[g] = newGreen;
// ?data[b] = newBlue;
You would have it easier if you would have an object oriented approach:
struct Pixel {
short red;
short green;
short blue;
};
Let your frame work with an std::vector<Pixel> pixels; which is returned by reference. std::vector<Pixel>& get_data();
pixels[y * width + x].red = newRed;
pixels[y * width + x].green = newGreen;
pixels[y * width + x].blue = newBlue;
If you really have to work with void* then try this
char* data = static_cast<char*>(const_cast<void*>(dataframe.get_data()));
// Since you also const cast it becomes more and more dangerous. You really need know what you are doing.
size_t bpp = frame.get_bytes_per_pixel();
size_t width = frame.get_width();
size_t height = frame.get_height();
size_t offset = (y * width * bpp) + (x * bpp);
size_t r = offset;
size_t g = offset + 1;
size_t b = offset + 2;
*(data + r) = newRed;
*(data + g) = newGreen;
*(data + b) = newBlue;
For bulk updates you can use memset.
See https://godbolt.org/z/xvc1xs for details.

RGBA pixel data into D3DLOCKED_RECT

I'm trying to update a 128x128 D3DLOCKED_RECT with sub images using the following code, but it seems to squish them down along the top, the X offset is ignored and the y offset is 60 percent off.
I've also tried to make the texture the correct size and copy it into a 128x128 texture at the correct location using RECT, however this is very slow and didn't seem to work correctly when I attempted it. There must be way to do it using the raw pixel data?
Any help would be much appreciated :)
EDIT: I got it semi working using the below code, the locations are now correct and the sizes. But it's only using the blue channel and everything is grey scale (blue scale?)
srcdata = (byte *) pixels;
dstdata = (unsigned int *)lockrect.pBits;
for (y = yoffset; y < (yoffset + height); y++)
{
for (x = xoffset; x < (xoffset + width); x++)
{
dstdata[ ( y * lockrect.Pitch / dstbytes + x ) + 0] = (unsigned int)srcdata[0];
dstdata[ ( y * lockrect.Pitch / dstbytes + x ) + 1] = (unsigned int)srcdata[1];
dstdata[ ( y * lockrect.Pitch / dstbytes + x ) + 2] = (unsigned int)srcdata[0];
dstdata[ ( y * lockrect.Pitch / dstbytes + x ) + 3] = (unsigned int)srcdata[3];
srcdata += srcbytes;
}
}'
END Edit
Test call after creating the 128x128 texture:
int x, y;
byte temp[132*132*4];
// Test texture (pink and black checker)
for( y = 0; y < 16; y++ )
{
for( x = 0; x < 16; x++ )
{
if(( y < 8 ) ^ ( x < 8 ))
((uint *)&temp)[y*16+x] = 0xFFFF00FF;
else ((uint *)&temp)[y*16+x] = 0xFF000000;
}
}
UpdateSubImage (0, 0, 16, 16, temp )
The update Fuction:
void UpdateSubImage (int xoffset, int yoffset, int width, int height, const
GLvoid *pixels)
{
int x, y;
int srcbytes = 4; //Hard coded for now, as all tests are RGBA
int dstbytes = 4; // ^
byte *srcdata;
byte *dstdata;
D3DLOCKED_RECT lockrect;
pTexture->LockRect( 0, &lockrect, NULL, 0);
srcdata = (byte *) pixels;
dstdata = (byte *) lockrect.pBits;
dstdata += (yoffset * width + xoffset) * dstbytes;
for (y = yoffset; y < (yoffset + height); y++)
{
for (x = xoffset; x < (xoffset + width); x++)
{
if (srcbytes == 1)
{
if (dstbytes == 1)
dstdata[0] = srcdata[0];
else if (dstbytes == 4)
{
dstdata[0] = srcdata[0];
dstdata[1] = srcdata[0];
dstdata[2] = srcdata[0];
dstdata[3] = srcdata[0];
}
}
else if (srcbytes == 3)
{
if (dstbytes == 1)
dstdata[0] = ((int) srcdata[0] + (int) srcdata[1] + (int) srcdata[2]) / 3;
else if (dstbytes == 4)
{
dstdata[0] = srcdata[2];
dstdata[1] = srcdata[1];
dstdata[2] = srcdata[0];
dstdata[3] = 255;
}
}
else if (srcbytes == 4)
{
if (dstbytes == 1)
dstdata[0] = ((int) srcdata[0] + (int) srcdata[1] + (int) srcdata[2]) / 3;
else if (dstbytes == 4)
{
dstdata[0] = srcdata[2];
dstdata[1] = srcdata[1];
dstdata[2] = srcdata[0];
dstdata[3] = srcdata[3];
}
}
// advance
srcdata += srcbytes;
dstdata += dstbytes;
}
}
pTexture->UnlockRect(0);
}
What the output looks like:
What the output should look like:
You're assuming that the data accessable through lockrect.pBits is linear in memory. This is in general not the case. Instead you have a constant offset between your rows which is defined by the lockrect.Pitch value.
To get the address of a pixel in the destination use:
byte * destAddr = (lockrect.pBits + y * lockrect.Pitch + 4 * x);
// for 32 bit images. For other formats adjust the hard-coded 4.
Thanks for the help :), in the end the following code worked:
Can it be made faster?
for (y = yoffset; y < (yoffset + height); y++)
{
for (x = xoffset; x < (xoffset + width); x++)
{
ARGB pixel;
pixel.r = srcdata[0];
pixel.g = srcdata[1];
pixel.b = srcdata[2];
pixel.a = srcdata[3];
memcpy( &dstdata[lockrect.Pitch * y + dstbytes * x], &pixel, dstbytes );
srcdata += srcbytes;
}
}

Create monochrome BMP from bitset

I could need some help to figure out how to feed the proc below. I need to write a monochrome BMP file. The code below (its from: How to Save monochrome Image as bmp in windows C++ ?) looks like to be able to do this. I'm now stuck on how to convert a std::bitset or preferably boost::dynamic_bitset into this byte* format. All of my attempts so far failed, I wasn't able to write something like an 8x8 checker pattern into the BMP. The proc creates the BMP and it is readable by Photoshop, but the content is a mess. So any suggestions how to solve this are appreciated!
Save1BppImage(byte* ImageData, const char* filename, long w, long h){
int bitmap_dx = w; // Width of image
int bitmap_dy = h; // Height of Image
// create file
std::ofstream file(filename, std::ios::binary | std::ios::trunc);
if(!file) return;
// save bitmap file headers
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER * infoHeader;
infoHeader = (BITMAPINFOHEADER*) malloc(sizeof(BITMAPINFOHEADER) );
RGBQUAD bl = {0,0,0,0}; //black color
RGBQUAD wh = {0xff,0xff,0xff,0xff}; // white color
fileHeader.bfType = 0x4d42;
fileHeader.bfSize = 0;
fileHeader.bfReserved1 = 0;
fileHeader.bfReserved2 = 0;
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + (sizeof(BITMAPINFOHEADER));
infoHeader->biSize = (sizeof(BITMAPINFOHEADER) );
infoHeader->biWidth = bitmap_dx;
infoHeader->biHeight = bitmap_dy;
infoHeader->biPlanes = 1;
infoHeader->biBitCount = 1;
infoHeader->biCompression = BI_RGB; //no compression needed
infoHeader->biSizeImage = 0;
infoHeader->biXPelsPerMeter = 0;
infoHeader->biYPelsPerMeter = 0;
infoHeader->biClrUsed = 2;
infoHeader->biClrImportant = 2;
file.write((char*)&fileHeader, sizeof(fileHeader)); //write bitmapfileheader
file.write((char*)infoHeader, (sizeof(BITMAPINFOHEADER) )); //write bitmapinfoheader
file.write((char*)&bl,sizeof(bl)); //write RGBQUAD for black
file.write((char*)&wh,sizeof(wh)); //write RGBQUAD for white
int bytes = (w/8) * h ; //for example for 32X64 image = (32/8)bytes X 64 = 256;
file.write((const char*)ImageData, bytes);
file.close();
}
-edit-
an naive approach of mine was something like this
byte test[64];
for(unsigned int i=0; i<64; ++i)
if(i % 2)
test[i] = 0;
else
test[i] = 1;
Save1BppImage(test, "C:/bitmap.bmp", 8, 8);
The code you have is very close. Here are a few thoughts about where it might be off.
The bfOffBits value must include the size of the palette.
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + (sizeof(BITMAPINFOHEADER)) + 2*sizeof(RGBQUAD);
Some software may interpret 0 as white and 1 as black, regardless of what the palette says. Even though the file format allows you to go either way, you're better off specifying the palette in that order and inverting your bits if necessary.
Each row of a bitmap will start on a 4-byte boundary. If your bitmap width isn't a multiple of 32, you're going to need some padding between each row.
BMP files are ordered from the bottom row to the top row, which is backwards from the way most people organize their arrays.
The last two recommendations are combined to look something like this:
int bytes_in = (w + 7) / 8;
int bytes_out = ((w + 31) / 32) * 4;
const char * zeros[4] = {0, 0, 0, 0};
for (int y = h - 1; y >= 0; --y)
{
file.write(((const char *)ImageData) + (y * bytes_in), bytes_in);
if (bytes_out != bytes_in)
file.write(zeros, bytes_out - bytes_in);
}
Just for the archive, below the working version. It takes a boost bitset as input pixel storage.
void bitsetToBmp(boost::dynamic_bitset<unsigned char> bitset, const char* filename, int width, int height){
//write the bitset to file as 1-bit deep bmp
//bit order 0...n equals image pixels top left...bottom right, row by row
//the bitset must be at least the size of width*height, this is not checked
std::ofstream file(filename, std::ios::binary | std::ios::trunc);
if(!file) return;
// save bitmap file headers
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER * infoHeader;
infoHeader = (BITMAPINFOHEADER*) malloc(sizeof(BITMAPINFOHEADER) );
RGBQUAD bl = {0,0,0,0}; //black color
RGBQUAD wh = {0xff,0xff,0xff,0xff}; // white color
fileHeader.bfType = 0x4d42;
fileHeader.bfSize = 0;
fileHeader.bfReserved1 = 0;
fileHeader.bfReserved2 = 0;
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + (sizeof(BITMAPINFOHEADER)) + 2*sizeof(RGBQUAD);
infoHeader->biSize = (sizeof(BITMAPINFOHEADER) );
infoHeader->biWidth = width;
infoHeader->biHeight = height;
infoHeader->biPlanes = 1;
infoHeader->biBitCount = 1;
infoHeader->biCompression = BI_RGB; //no compression needed
infoHeader->biSizeImage = 0;
infoHeader->biXPelsPerMeter = 0;
infoHeader->biYPelsPerMeter = 0;
infoHeader->biClrUsed = 2;
infoHeader->biClrImportant = 2;
file.write((char*)&fileHeader, sizeof(fileHeader)); //write bitmapfileheader
file.write((char*)infoHeader, (sizeof(BITMAPINFOHEADER) )); //write bitmapinfoheader
file.write((char*)&bl,sizeof(bl)); //write RGBQUAD for black
file.write((char*)&wh,sizeof(wh)); //write RGBQUAD for white
// convert the bits into bytes and write the file
int offset, numBytes = ((width + 31) / 32) * 4;
byte* bytes = (byte*) malloc(numBytes * sizeof(byte));
for(int y=height - 1; y>=0; --y){
offset = y * width;
memset(bytes, 0, (numBytes * sizeof(byte)));
for(int x=0; x<width; ++x)
if(bitset[offset++]){
bytes[x / 8] |= 1 << (7 - x % 8);
};
file.write((const char *)bytes, numBytes);
};
free(bytes);
file.close();
}
I wonder if theres a simpler/faster way to put the bits into a file? The whole bitset could instead be overhanded as array of rows to skip the subset extraction.
I have something very similiar...
This approach DOES NOT treat the padding of the BMP format. So You can only make bitmaps with width multiple of 4.
This is NOT a monochromatic bitmap. It's a RGB format, but you can tune it easily.
This is NOT an exactly answer to you, but for sure may be useful for you.
Enjoy it.
void createBitmap( byte * imageData, const char * filename, int width, int height )
{
BITMAPFILEHEADER bitmapFileHeader;
memset( &bitmapFileHeader, 0, sizeof( bitmapFileHeader ) );
bitmapFileHeader.bfType = ( 'B' | 'M' << 8 );
bitmapFileHeader.bfOffBits = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER );
bitmapFileHeader.bfSize = bitmapFileHeader.bfOffBits + width * height * 3;
BITMAPINFOHEADER bitmapInfoHeader;
memset( &bitmapInfoHeader, 0, sizeof( bitmapInfoHeader ) );
bitmapInfoHeader.biSize = sizeof( BITMAPINFOHEADER );
bitmapInfoHeader.biWidth = width;
bitmapInfoHeader.biHeight = height;
bitmapInfoHeader.biPlanes = 1;
bitmapInfoHeader.biBitCount = 24;
std::ofstream file( filename, std::fstream::binary );
file.write( reinterpret_cast< char * >( &bitmapFileHeader ), sizeof( bitmapFileHeader ) );
file.write( reinterpret_cast< char * >( &bitmapInfoHeader ), sizeof( bitmapInfoHeader ) );
// the pixels!
file.write( imageData, width * height * 3 );
file.close();
}
int main( int argc, const char * argv[] )
{
int width = 12; // multiple of 4
int height = 12;
byte imageData[ width * height * 3 ];
// fill imageData the way you want, this is just a sample
// on how to set the pixel at any specific (X,Y) position
for ( int y = 0; y < height; ++y )
{
for ( int x = 0; x < width; ++x )
{
int pos = 3 * ( y * width + x );
byte pixelColor = ( x == 2 && y == 2 ) ? 0x00 : 0xff;
imageData[ pos ] = pixelColor;
imageData[ pos + 1 ] = pixelColor;
imageData[ pos + 2 ] = pixelColor;
}
}
createBitmap( imageData, "bitmap.bmp", width, height );
return 0;
}
In this sample we want a white bitmap with a single black pixel at position X = 2, Y = 2.
The BMP format constiders that Y grows up from bottom to top.
If you have a bitmap width a pixel per bit (the real monochromatic bitmap) you can test the bits and fill the imageData. To test a bit in a byte do like myByte >> position & 1 where position is the bit you wanna test from 0 to 7.

How do I write raw pixel data and save as a bitmap

My problem is this: I wanna try to make a white color 24bit bitmap, but everytime I write to the bmp file, it gives me white black/white stripes. i dont understand why? Maybe i skip some bytes?
If you want more information on the code just ask.
setup settings:
void setup_settings( ) {
// information om billedet
pic.infoHeader.biSize = sizeof(BMP_InfoHeader);
pic.infoHeader.biBitCount = 24;
pic.infoHeader.biWidth = WIDTH; // Hoejte i pixels
pic.infoHeader.biHeight = HEIGH; // bredte i pixels
pic.infoHeader.biPlanes = 1;
pic.infoHeader.biCompression = 0;
pic.infoHeader.biSizeImage = WIDTH * HEIGH * (pic.infoHeader.biBitCount/8);
pic.infoHeader.biXPelsPerMeter = 0;
pic.infoHeader.biYPelsPerMeter = 0;
pic.infoHeader.biClrUsed = 0;
pic.infoHeader.biClrInportant = 0;
pic.fileHeader.bfType[0] = 'B';
pic.fileHeader.bfType[1] = 'M';
pic.fileHeader.bfReservered1 = pic.fileHeader.bfReservered2 = 0;
pic.fileHeader.bfOffBits = sizeof(BMP_FileHeader) + pic.infoHeader.biSize;
}
this funktion definition for my SaveBitmapFile is:
int SaveBitmapFile(const std::string filename, bit24* image){
// gem filen
std::ofstream writer(FileName.c_str(), std::ofstream::binary);
if(!writer.is_open()){
printf("Error: While Writing\n");
return -1;
}
writer.write(reinterpret_cast<char *>(&pic.fileHeader), sizeof(BMP_FileHeader) );
writer.write(reinterpret_cast<char *>(&pic.infoHeader), sizeof(BMP_InfoHeader) );
writer.write(reinterpret_cast<char*>(&image[0]), pic.infoHeader.biSizeImage);
writer.close();
return 0;
}
My structures:
#pragma pack(1)
typedef struct{
uint32_t value : 24;
}bit24;
#pragma pack(0)
// Billedet
#pragma pack(1)
typedef struct{
unsigned int Width;
unsigned int Heigh;
bit24* RGB;
}Image;
#pragma pack(0)
typedef struct {
BMP_FileHeader fileHeader;
BMP_InfoHeader infoHeader;
Image data;
}BMP_Data;
My source main source code:
// the pic is a type of BMP_Data. sorry if i this is really messy.
int main( int argc, char *argv[] ){
setup_settings();
pic.data.Heigh = pic.infoHeader.biHeight;
pic.data.Width = pic.infoHeader.biWidth;
int bytesPerRGB = (pic.infoHeader.biBitCount/8);
//padded bytes?
int paddedBytes = ( pic.data.Width * bytesPerRGB) % 4;
printf("PaddedBytes: %d\n", paddedBytes);
pic.data.RGB = new bit24[ pic.data.Heigh * pic.data.Width * bytesPerRGB];
uint8_t r,g,b;
r = 0xFF;
g = 0xFF;
b = 0xFF;
/*
for( unsigned int y = 0; y < pic.data.Heigh; y++)
for( unsigned int x = 0; x < pic.data.Width; x++)
{
pic.data.RGB[x + (y*pic.data.Width )].value = ( (b << 0) | (g << 8) | (r << 16) );
}
*/
for( unsigned int i = 0; i < pic.data.Heigh * pic.data.Width * bytesPerRGB; i+=3){
pic.data.RGB[i ].value = ( (b << 0) | (g << 8) | (r << 16) );
}
SaveBitmapFile(FileName, pic.data.RGB);
delete [] pic.data.RGB;
return 0;
}
You MUST fill all BitmapInfoHeader fields.
- Assuming you want 24bits bitmap:
BITMAPINFOHEADER bi =
{
sizeof(BITMAPINFOHEADER), // DWORD, = 40
WIDTH, // DWORD, image width in pix
HEIGHT, // DWORD, image width in pix
1, // WORD, planes MUST be 1
24,// WORD, num of bits per pixel
BI_RGB, // DWORD, (no compression = BI_RGB = 0)
0, // DWORD, sizeof image data, can be 0 if BI_RGB = 0
0, // DWORD, x-resolution
0, // DWORD, y-resolution
0, // DWORD, colors used (palette images only)
0, // DWORD, importand colors (palette images only)
};
Also make sure every row (horizontal line) of pixels is padded to multiple of 4 bytes !!!
(So begin with images of N x 4 width - they have no padding issues)
Okay, I have found the problem.
After I changed the bit24 to:
typedef struct{
uint8_t blue;
uint8_t green;
uint8_t red;
}RGB_Data;
from:
#pragma pack(1)
typedef struct{
uint32_t value : 24;
}bit24;
#pragma pack(0)
and a little change in the main:
for( unsigned int i = 0; i < pic.data.Heigh * pic.data.Width * bytesPerRGB; i++){
pic.data.RGB[i].blue = b;
pic.data.RGB[i].green = g;
pic.data.RGB[i].red = r;
}
it worked like a charm. thanx you for your help :)

How to access a RGB image data

I want the data at pixel to be compared with the colour and then i want to find contour then take centroid points of the contour ,so i am using like this to find countourdata am i wrong at this statement
int pos = i * w * Channels + j; //channels is 3 as rgb
// if any data exists
if (data->imageData[pos]>0)
Code is like this
for (int i = x; i < x+h; i++) //height of frame pixels
{
for (int j = y; j < y+w; j++)//width of frame pixels
{
int pos = i * w * Channels + j; //channels is 3 as rgb
// if any data exists
if (data->imageData[pos]>0) //Taking data (here is the problem how to take)
{
xPos += j;
yPos += i;
nPix++;
}
}
}
I use the following code structure
/**
* #brief Calculate greeness from an RGB image
*
* Performs the greeness pixelwise transform on the input image.
* Greeness is defined as
* Greeness = 255*G/sqrt(R^2+G^2+B^2)
* The function assumes that the resolution of the two images are identical.
*
* #param imSrc Input RGB image.
* #param imDst Output grayscale (greeness) image.
*/
void rgbToGreeness( IplImage *imSrc , IplImage* imDst) {
// Allocate variables
int tmp_pix;
uchar * _SrcPtr, * _DstPtr;
// Iterate over the image line by line
for(int y = 0 ; y < imSrc->height ; y++ )
{
// Locate pointers to the first data element in the current line
_SrcPtr = ( uchar* )( imSrc->imageData + y * imSrc->widthStep );
_DstPtr = ( uchar* )( imDst->imageData + y * imDst->widthStep );
// Iterate over the elements in the current line
for( int x = 0 ; x < imSrc->width ; x++ )
{
//2*G-B-R - Excessive green
tmp_pix = (int) (255*_SrcPtr[3*x+1]/pow(pow((float)_SrcPtr[3*x],2) + pow((float)_SrcPtr[3*x+1], 2) + pow((float)_SrcPtr[3*x+2], 2), (float) 0.5));
//If value is larger than 255, set it to 255 and lower than 0 set it to 0
_DstPtr[x] = (uchar) ( ( tmp_pix < 0 ) ? 0 : ( ( tmp_pix > 255 ) ? 255 : tmp_pix ) );
}
}
}
Here is some code to access RGB data of a pixel in an image
IplImage* img=cvLoadImage(fileName);
CvScalar s;
s=cvGet2D(img,i,j); // get the (i,j) pixel value
s.val[0]=111; // B-channel
s.val[1]=111; // G-channel
s.val[2]=111; // R-channel
cvSet2D(img,i,j,s); // set the (i,j) pixel value
Source (modified a little): http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html#SECTION00053000000000000000
As requested here is my exact code where i want to calculate centroids from contour
My exact code is like this
1) Taking RGB image as input
2) x=0,y=0,w=width of frame,h=height of frame.are the data passing
void cRecursiveCentroids::ComputeCentroid(int x, int y, int w, int h, IplImage *data, bool splitOnUpDown, int level, int id, int addToId){
if (level == m_Levels-1 ) return;
int Channels = data->nChannels; // Number of channels
std::cout << "Channels: " << Channels << "\n";
int xPos = 0;
int yPos = 0;
int nPix = 0;
for (int i = x; i < x+h; i++) //Tracing the contour
{
for (int j = y; j < y+w; j++)
{
int pos = i * m_Wid * Channels + j; // Here may be the error i am thinking
// if any data exists
if (data->imageData[pos]>0)
{
xPos += j;
//std::cout << "xPos: " << xPos << "\n";
yPos += i;
// std::cout << "yPos: " << yPos << "\n";
nPix++;
}
}
}
Check = nPix;
if (nPix > 0){ // Calculating Position
xPos = (int)((float)xPos / (float)nPix);
yPos = (int)((float)yPos / (float)nPix);
int num = ( id + addToId ) > 16 ? 16 : (id+addToId);
m_Cent[num].posx = xPos;
m_Cent[num].posy = yPos;
m_Cent[num].level = level;
splitOnUpDown = !splitOnUpDown;
level = level+1;
if (splitOnUpDown) //Recursive calling for centroids
{
id *= 2;
ComputeCentroid(x,y,w,(yPos - y), data, splitOnUpDown, level, id, addToId);
ComputeCentroid(x,yPos,w,h-(yPos-y), data, splitOnUpDown, level, id+1, addToId);
} else {
id *= 2;
ComputeCentroid(x,y,(xPos-x),h, data, splitOnUpDown, level, id, addToId);
ComputeCentroid(xPos,y,w - (xPos-x),h, data, splitOnUpDown, level, id+1, addToId);
}
}
DrawCentroidPoints(); //Draw Centroid Points
}