Когда я проверил код у вас есть это:
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];
}
}
EDIT
Этот раздел вашего кода может вызывать озабоченность:
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;
}
Вы объявляете ваш массив для хранения unsigned int, пока данные пикселя сохраняются в виде символа, а затем вы пытаетесь сохранить этот тип char в массив unsigned int. Это может помочь, если вы измените свой символ на символ без знака. Я также включаю демонстрацию метода для одного из моих классов для чтения в 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 Graphics Engine.
Как вы можете видеть здесь, я использую структуру для заголовка TGA; У меня также есть структура для объекта Texture. Теперь все это может быть больше, чем вам нужно; но важные части видят, как я читаю данные из файла и сохраняю их значения.
Важная часть, где я использую ключевое слово C++ reinterpret_cast<>()
в потоках файлов read()
. Это может помочь вам переписать ваш синтаксический анализатор для чтения в файле изображения, чтобы данные, которые вы читаете и хранящие, выровнены по строкам с той структурой изображения, которую вы ожидаете. Это также будет зависеть от структуры файла, который вы читаете, и структуры изображения, которую вы используете в своем коде.
У меня также есть аналогичный метод для чтения в PNG-файле, который использует этот класс, который зависит от библиотеки PGN, где я установлен на моем компьютере, и связан с моей IDE, поэтому функции для чтения в PGN-файле могут быть найденный. Это довольно немного проще, чем функция, которую я показал вам здесь для чтения в TGA-файле.
Если вы хотите использовать TGA-файл, вам необходимо знать структуру файла и написать собственный файловый парсер, где, как и в файле PNG, большая часть этой работы выполняется для вас в библиотеке PNG, и все, что вам нужно будет сделать вызывает соответствующие функции в правильном порядке и проверяет наличие соответствующих ошибок. Я не показывал функцию loadPNG().
Конечно, вы читаете файл PGM, а не TGA или PNG, но концепция такая же. Вы должны точно знать, сколько байтов для чтения, прежде чем вы достигнете фактических данных пикселя, тогда вы должны знать размер изображения, как в пиксельной ширине * длина пикселя * байт на пиксель. Информация заголовка должна рассказать вам об этом, так как вы читаете это и храните его в своих переменных или структурах, но это очень важно. Примером может служить изображение, скажем, 256 пикселей X 256 пикселей, однако то, что также должно быть известно, - это то, насколько широкий пиксель! Каждый пиксель 8 бит (1 байт), 16 бит (2 байта), 24 бита (3 байта), 32 бита (4 байта). Еще одна важная вещь, которую нужно знать, это то, что такое цветной рисунок, например черный & белый, серый, RGB, RGBA, CYM и т. Д., И в каком порядке сохраняется информация о цвете. Также изображение сохраняется как инвертированное не только по цветной информации, но и изображение, переворачиваемое по горизонтали или по вертикали. Обычно в заголовке файла изображения есть флаги, которые расскажут вам об этом. Кроме того, сжатые, несжатые данные - это необработанные данные или длина пробега (RLE). Вся эта информация важна при анализе файла изображения. Когда вы работаете с BMP-JPEG, это даже немного усложняется, потому что у них также есть возможная цветовая палитра.
Я надеюсь, что это поможет вам служить в качестве руководства, чтобы вы могли правильно прочитать в своем файле изображения, прежде чем приступать к обработке или работе с данными изображения.
Я знаю, что означает «интеграл» и «изображение», но я не уверен в «целостном изображении». Можете ли вы объяснить, что вы делаете? – duffymo
Вы не можете получить доступ к двумерному массиву следующим образом: integ [i, j]. Он должен быть интегральным [i] [j]. –
Интегральное изображение представляет собой структуру данных и алгоритм для быстрого и эффективного генерирования суммы значений в прямоугольном подмножестве сетки. Вот введение на wiki-странице: https: //en.wikipedia.org/wiki/Summed_area_table – Myliecielo