当我检查你的代码时,你有这个:
for (int j = 0; j < num_of_rows; j++){ //compute integral image
for (int i = 0; i < num_of_cols; i++){
integral[i, j] = integral[i - 1, j] +
integral[i, j - 1] -
integral[i - 1, j - 1] +
pixel_value[i, j];
}
}
我认为你的意思是这样的:
for (int j = 0; j < num_of_rows; j++){ //compute integral image
for (int i = 0; i < num_of_cols; i++){
integral[i, j] = integral[i - 1][j] +
integral[i][j - 1] -
integral[i - 1][j - 1] +
pixel_value[i][j];
}
}
编辑
这部分代码可能值得关注:
int max_val; //255
ss >> max_val;
cout<<max_val;
char pixel;
unsigned int pixel_value[num_of_rows][num_of_cols];
unsigned int integral[num_of_rows][num_of_cols];
for (row = 0; row < num_of_rows; row++){ //pixel values
for (col = 0; col < num_of_cols; col++){
ss >> pixel;
pixel_value[row][col]= pixel;
}
cout << endl;
}
在将像素数据保存为 char 类型时,您声明数组保存 unsigned int,然后您尝试将此 char 类型保存到 unsigned int 数组中。如果您将 char 更改为 unsigned char 可能会有所帮助。我还包括了我的一个类的方法的演示,用于在下面的 TGA 文件中读取。
我正在查看您关于如何读取数据的方法,它可能会帮助您查看我的一个类的函数定义的实现,该类将从 TGA 文件中读取数据.这是提供的结构和函数定义。
// TextureInfo -------------------------------------------------------------
struct TextureInfo {
enum FilterQuality {
FILTER_NONE = 1,
FILTER_GOOD,
FILTER_BETTER,
FILTER_BEST
}; // FilterQuality
unsigned uTextureId;
bool hasTransparency;
glm::uvec2 size;
TextureInfo() :
uTextureId( INVALID_UNSIGNED ),
hasTransparency( false ),
size( glm::uvec2( 0, 0 ) )
{}
}; // TextureInfo
// -------------------------------------------------------------------------
// Texture
struct Texture {
bool hasAlphaChannel;
bool generateMipMap;
bool wrapRepeat;
unsigned uWidth;
unsigned uHeight;
TextureInfo::FilterQuality filterQuality;
std::vector<unsigned char> vPixelData;
Texture( TextureInfo::FilterQuality filterQualityIn, bool generateMipMapIn, bool wrapRepeatIn ) :
hasAlphaChannel( false ),
generateMipMap( generateMipMapIn ),
wrapRepeat( wrapRepeatIn ),
uWidth( 0 ),
uHeight( 0 ),
filterQuality( filterQualityIn )
{}
}; // Texture
// -------------------------------------------------------------------------
// loadTga()
void TextureFileReader::loadTga( Texture* pTexture ) {
if ( nullptr == pTexture ) {
throw ExceptionHandler( __FUNCTION__ + std::string( " invalid pTexture passed in" ) );
}
struct TgaHeader {
unsigned char idLength;
unsigned char colorMapType;
unsigned char imageType;
unsigned char colorMapSpecifications[5];
short xOrigin;
short yOrigin;
short imageWidth;
short imageHeight;
unsigned char pixelDepth;
unsigned char imageDescriptor;
} tgaHeader;
enum TgaFileType {
TGA_RGB = 2,
TGA_RLE_RGB = 10,
}; // TgaFileType
// Error Message Handling
std::ostringstream strStream;
strStream << __FUNCTION__ << " ";
// Open File For Reading
m_fileStream.open( m_strFilenameWithPath, std::ios_base::in | std::ios_base::binary );
if ( !m_fileStream.is_open() ) {
strStream << "can not open file for reading";
throwError( strStream );
}
// Get TGA File Header
if ( !m_fileStream.read( reinterpret_cast<char*>( &tgaHeader ), sizeof( tgaHeader ) ) ) {
strStream << "error reading header";
throwError( strStream );
}
// This TGA File Loader Can Only Load Uncompressed Or Compressed True-Color Images
if ( (tgaHeader.imageType != TGA_RGB ) && (tgaHeader.imageType != TGA_RLE_RGB ) ) {
strStream << "TGA loader only supports loading RGB{" << TGA_RGB << "} and RLE_RGB{" << TGA_RLE_RGB
<< "} encoded files. This file contains pixels encoded in an unsupported type{" << tgaHeader.imageType << "}";
throwError( strStream );
}
// Convert Bits Per Pixel To Bytes Per Pixel
unsigned uBytesPerPixel = tgaHeader.pixelDepth / 8;
if ( (uBytesPerPixel != 3) && (uBytesPerPixel != 4) ) {
strStream << "TGA loader only supports 24bpp or 32bpp images. This image uses " << tgaHeader.pixelDepth << " bits per pixel";
throwError( strStream );
}
// Make Room For All Pixel Data
if ( 0 == tgaHeader.imageWidth || 0 == tgaHeader.imageHeight ) {
strStream << "invalid image size (" << tgaHeader.imageWidth << "," << tgaHeader.imageHeight << ")";
throwError( strStream );
}
unsigned uTotalNumBytes = tgaHeader.imageWidth * tgaHeader.imageHeight * uBytesPerPixel;
pTexture->vPixelData.resize( uTotalNumBytes );
// Move Read Pointer To Beginning Of Image Data
if ( tgaHeader.idLength > 0 ) {
m_fileStream.ignore( tgaHeader.idLength );
}
// Used To Get And Flip Pixels Data
std::vector<unsigned char> vTempPixel( uBytesPerPixel, 0 );
if ( tgaHeader.imageType == TGA_RLE_RGB ) {
// TGA Data Is Compressed
// All Error Messages The Same If Error Occurs Below
strStream << "file is corrupted, missing pixel data";
unsigned char ucRepetitionCounter = 0;
unsigned uTotalNumberPixels = tgaHeader.imageWidth * tgaHeader.imageHeight;
unsigned uCurrentPixel = 0;
while( uCurrentPixel < uTotalNumberPixels ) {
// Get Repetition Count Value
if ( !m_fileStream.read( reinterpret_cast<char*>( &ucRepetitionCounter ), sizeof( unsigned char ) ) ) {
throwError( strStream );
}
if ( ucRepetitionCounter < 128 ) {
// Raw Packet. Counter Indicates How Many Different Pixels Need To Be Read
++ucRepetitionCounter;
// Get Pixel Values
if ( !m_fileStream.read( reinterpret_cast<char*>( &pTexture->vPixelData[uCurrentPixel * uBytesPerPixel] ), uBytesPerPixel * ucRepetitionCounter ) ) {
throwError( strStream );
}
} else {
// Run-Length Packet. Counter Indicates How Many Times The Text Pixel Needs To Repeat
ucRepetitionCounter -= 127;
// Get Pixel Value
if ( !m_fileStream.read( reinterpret_cast<char*>( &vTempPixel[0] ), uBytesPerPixel ) ) {
throwError( strStream );
}
// Save Pixel Multiple Times
for ( unsigned int u = uCurrentPixel; u < ( uCurrentPixel + ucRepetitionCounter ); ++u ) {
memcpy( &pTexture->vPixelData[u * uBytesPerPixel], &vTempPixel[0], uBytesPerPixel );
}
}
// Increment Counter
uCurrentPixel += ucRepetitionCounter;
}
} else {
// TGA Data Is Uncompressed
// Get Pixel Data
if ( !m_fileStream.read( reinterpret_cast<char*>( &pTexture->vPixelData[0] ), pTexture->vPixelData.size() ) ) {
strStream << "file is corrupted, missing pixel data";
throwError( strStream );
}
}
m_fileStream.close();
// Convert All Pixel Data from BGR To RGB
unsigned char ucTemp;
for ( unsigned int u = 0; u < uTotalNumBytes; u += uBytesPerPixel ) {
ucTemp = pTexture->vPixelData[u]; // Save Blue Color
pTexture->vPixelData[u] = pTexture->vPixelData[u + 2]; // Set Red Color
pTexture->vPixelData[u + 2] = ucTemp; // Set Blue Color
}
// Flip Image Horizontally
if ( tgaHeader.imageDescriptor & 0x10 ) {
short sHalfWidth = tgaHeader.imageWidth >> 1;
for ( short h = 0; h < tgaHeader.imageHeight; ++h ) {
for ( short w = 0; w < sHalfWidth; ++w ) {
unsigned uPixelLeft = uBytesPerPixel * ( h * tgaHeader.imageWidth + w );
unsigned uPixelRight = uBytesPerPixel * ( h * tgaHeader.imageWidth + tgaHeader.imageWidth - 1 - w );
memcpy( &vTempPixel[0], &pTexture->vPixelData[uPixelLeft], uBytesPerPixel ); // Store Left Pixel
memcpy( &pTexture->vPixelData[uPixelLeft], &pTexture->vPixelData[uPixelRight], uBytesPerPixel ); // Save Right Pixel @ Left
memcpy( &pTexture->vPixelData[uPixelRight], &vTempPixel[0], uBytesPerPixel ); // Save Left Pixel @ Right
}
}
}
// Flip Vertically
if ( tgaHeader.imageDescriptor & 0x20 ) {
short sHalfHeight = tgaHeader.imageHeight >> 1;
for ( short w = 0; w < tgaHeader.imageWidth; ++w ) {
for ( short h = 0; h < sHalfHeight; ++h ) {
unsigned uPixelTop = uBytesPerPixel * ( w + tgaHeader.imageWidth * h );
unsigned uPixelBottom = uBytesPerPixel * ( w + tgaHeader.imageWidth * ( tgaHeader.imageHeight - 1 - h ) );
memcpy( &vTempPixel[0], &pTexture->vPixelData[uPixelTop], uBytesPerPixel ); // Store Top Pixel
memcpy( &pTexture->vPixelData[uPixelTop], &pTexture->vPixelData[uPixelBottom], uBytesPerPixel ); // Save Bottom Pixel @ Top
memcpy( &pTexture->vPixelData[uPixelBottom], &vTempPixel[0], uBytesPerPixel ); // Save Top Pixel @ Bottom
}
}
}
// Store Other Values In Texture
pTexture->uWidth = tgaHeader.imageWidth;
pTexture->uHeight = tgaHeader.imageHeight;
pTexture->hasAlphaChannel = ( tgaHeader.pixelDepth == 32 );
} // loadTga
注意: - 如果您复制和粘贴它依赖于此处未列出或显示的其他类和库,它将无法编译。这是来自我的 3D 图形引擎解决方案之一的有效工作代码。
正如您在此处看到的,我正在使用 TGA Header 的结构;我还有一个纹理对象的结构。现在所有这些可能都超出了您的需要;但重要的部分是了解我如何从文件中读取数据并存储它们的值。
重要的部分是我在文件流read() 方法中使用C++ 关键字reinterpret_cast<>( )。这可以帮助您重写解析器以读取图像文件,以便您正在读取和存储的数据与您期望的图像结构字节对齐。这还取决于您正在阅读的文件的结构以及您在代码中使用的图像结构。
我也有类似的方法来读取此类使用的 PNG 文件,这取决于我将它安装在我的电脑上并链接到我的 IDE 的 PGN 库,因此可以找到用于读取 PGN 文件的函数.这比我在这里展示的用于读取 TGA 文件的函数要简单得多。
当您想使用 TGA 文件时,您必须了解文件结构并编写自己的文件解析器,其中与 PNG 文件一样,大部分工作都在 PNG 库中为您完成,您所要做的就是以正确的顺序调用相应的函数并检查相应的错误。我没有展示 loadPNG() 函数。
当然,您阅读的是 PGM 文件,而不是 TGA 或 PNG,但概念是相同的。在到达实际像素数据之前,您必须确切知道要读取多少字节,然后您应该知道图像的大小,如像素宽度 * 像素长度 * 每个像素的字节数。标题信息应该在您读入并将其存储到您的变量或结构中时告诉您这么多,但这非常重要。一个例子是图像是 256 像素 X 256 像素,但是还需要知道每个像素的宽度!每个像素是8bits(1bytes)、16bits(2bytes)、24bits(3bytes)、32bits(4bytes)。另一个需要了解的重要事项是黑白、灰度、RGB、RGBA、CYM 等颜色模式是什么,以及颜色信息的存储顺序。此外,图像存储为不仅通过颜色信息反转,而且图像水平和/或垂直翻转。图像文件的标头信息中通常有一些标志会告诉您这一点。数据是压缩的,未压缩的,是原始数据还是运行长度编码(RLE)。在解析图像文件时,所有这些信息都很重要。当您使用 BMP - JPEG 时,它甚至会变得更复杂一些,因为它们还存储了可能的调色板。
我希望这有助于为您提供指导,以便您可以在开始对图像数据进行任何处理或处理之前正确读取图像文件。