Access Pixel Color to Find Brightness of Rendered Image

Problems building or running the engine, queries about how to use features etc.
Post Reply
HenryValentine
Gnoblar
Posts: 2
Joined: Thu Nov 23, 2017 10:30 pm

Access Pixel Color to Find Brightness of Rendered Image

Post by HenryValentine » Sat Jan 06, 2018 10:00 pm

Hello All,

I'm writing an application in which I need to retrieve the "brightness" of each frame that is rendered.

In order to do this, I'm trying to access the color of each pixel from the viewport, average the R, G, and B values from each pixel, find the total sum of the RGB values across the entire image, and divide by 255 times the total number of pixels in the image in order to find a normalized "brightness" value. (Note: For the purpose of my application, there is no need to weight the RGB channels according to their perceived brightness to the human eye).

The following code is called for every rendered frame.

Code: Select all

// Using the Third MipMap of the RTT texture
Ogre::HardwarePixelBufferSharedPtr pixelBuff = m_rttTexture->getBuffer(0, 3); 

pixelBuff->lock(Ogre::HardwareBuffer::HBL_READ_ONLY); // Lock for Reading Pixel Data

PixelBox pBox = pixelBuff->getCurrentLock(); // Retrieve Current Frame

int width  = pBox.getWidth();
int height = pBox.getHeight();

double totalColor = 0;

// Iterate Through Image
for(int i = 0; i < width; i++)
{ 
	for (int j = 0; j < height; j++)
	{
		// Access RGB Color of each Pixel and append to the totalColor value
		totalColor += pBox.getColourAt(i, j, 1).r / 3;
		totalColor += pBox.getColourAt(i, j, 1).g / 3;
		totalColor += pBox.getColourAt(i, j, 1).b / 3;
	}
}

// Divide total Color by total number of pixels * 255
double brightness = totalColor / (double)(width * height * 255);

std::cout << "Brightness: " << brightness << "\n";

// Unlock Buffer
pixelBuff->unlock();
The following is my initial Render to Texture setup called once at the beginning of the program. The texture is created with 3 MipMaps and one of these is accessed by the code above in order to find the brightness of the image. The idea is that by using MipMaps, I can reduce the total number of pixels that need to be iterated through and still obtain the average brightness value of the image (albeit at a hefty loss of precision).

Code: Select all

m_rttTexture =
		Ogre::TextureManager::getSingleton().createManual(
			"RttTex",
			Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
			Ogre::TEX_TYPE_2D,
			getRenderWindow()->getWidth(), getRenderWindow()->getHeight(),
			3,
			Ogre::PF_R8G8B8,
			Ogre::TU_RENDERTARGET
		);

m_renderTexture = m_rttTexture->getBuffer()->getRenderTarget();

m_renderTexture->addViewport(m_camera);
m_renderTexture->getViewport(0)->setClearEveryFrame(true);
m_renderTexture->getViewport(0)->setBackgroundColour(Ogre::ColourValue::Black);
m_renderTexture->getViewport(0)->setOverlaysEnabled(false);

I'm getting values for brightness and totalColor, but they do not appear to be correct (e.g I'm getting a brightness reading when the viewport is totally black and I should get a 0).

I'm very new to Ogre, so I'm obviously not sure as to whether or not this is an efficient or valid approach. Any ideas on what I'm doing wrong?

Thank You!
0 x

HenryValentine
Gnoblar
Posts: 2
Joined: Thu Nov 23, 2017 10:30 pm

Re: Access Pixel Color to Find Brightness of Rendered Image

Post by HenryValentine » Fri Jan 12, 2018 6:18 pm

Ok, so I've been working on it more and I've since realized that my previous approach was incorrect :p

Here is the updated code. I effectively just mimicked the RenderTarget::writeContentsToFile(Ogre::String &fileName) function in that it creates an Image object from the Rendered Texture. Instead of saving the image to a file, however, I simply read the pixel values directly.

Code: Select all

// Pixel Format
PixelFormat pf = m_renderTexture->suggestPixelFormat();

// Width and Height of Texture
int width  = m_renderTexture->getWidth();
int height = m_renderTexture->getHeight();


// Allocate Memory for the Pixel Data
uchar *data = OGRE_ALLOC_T(uchar, width * height * PixelUtil::getNumElemBytes(pf), MEMCATEGORY_RENDERSYS);

// Destination Pixel Box
PixelBox pBox = PixelBox(width, height, 1, pf, data); 

// Copy Teture Contents to Memory
m_renderTexture->copyContentsToMemory(pBox, pBox);

// Access Data Through an Image Object
Image img = Image().loadDynamicImage(data, width, height, 1, pf, false, 1, 0);

// Total Color
double totalColor = 0;

// Iterate Through Image
for (int i = 0; i < width; i++)
{
	for (int j = 0; j < height; j++)
	{
		totalColor += img.getColourAt(i, j, 0).r / 3;	
		totalColor += img.getColourAt(i, j, 0).g / 3;
		totalColor += img.getColourAt(i, j, 0).b / 3;
	}
}

img.freeMemory();

// Free the Data
OGRE_FREE(data, MEMCATEGORY_RENDERSYS);

double brightness = totalColor / (double)(width * height);


Not sure as to whether or not this is the most efficient method at this point, but it is working.
Let me know if there are any other ideas!
0 x

Post Reply