Фильтр LoG для изображения в градациях серого, сохраненного в виде двоичного файла - PullRequest
0 голосов
/ 06 января 2019

Я пытаюсь реализовать фильтр LoG для изображения со статической маской 5x5 и сверткой, закодированной в функции applyFilter(). Однако я получаю странные результаты, независимо от того, какую маску я применяю. Сохранение изображения без прохождения его через функцию работает, поэтому проблема прямо здесь, кто-нибудь может дать мне какие-либо предложения, что с ним не так?

Изображение читается из каталога на основе измерений, передаваемых в CLI во время выполнения сценария, т. Е. / 1200 1500 1200 открывает изображение infile1500_1200.bin

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <chrono>

typedef std::vector<uint8_t> vec;
typedef std::vector<vec> matrix;
typedef std::vector<double> kernelRow;
typedef std::vector<kernelRow> kernel;

matrix toMatrix(const vec &flat_vec, std::size_t ncols)
{
    const auto nrows = flat_vec.size() / ncols;
    matrix mtx;
    const auto begin = std::begin(flat_vec);
    for (std::size_t row = 0; row < nrows; ++row) {
        mtx.push_back({ begin + row * ncols, begin + (row + 1)*ncols });
    }
    return mtx;
}

vec readFile(std::string fileName)
{
    std::ifstream inFile;
    vec rawFileBuffer;
    std::cout << "Reading image: " << fileName << std::endl;
    inFile.open(fileName, std::ios::in | std::ios::binary);
    inFile.seekg(0, std::ios::end);
    size_t filesize = inFile.tellg();
    inFile.seekg(0, std::ios::beg);
    rawFileBuffer.resize(filesize / sizeof(uint8_t));
    inFile.read((char *)rawFileBuffer.data(), filesize);
    inFile.close();
    return rawFileBuffer;
}

matrix getImageByFilename(std::string filename, int row)
{
    vec fileContent = readFile(filename);
    matrix image = toMatrix(fileContent, row);
    return image;
}

void saveImage(std::string fileName, matrix image)
{
    std::ofstream output(fileName, std::ios::out | std::ios::binary);
    for (const auto &row : image)
    {
        for (const auto &col : row)
        {
            output << col;
        }
    }
    output.close();
    std::cout << "File: " << fileName << "is saved." << std::endl;
}


kernel getLogKernel()
{
    kernel kernel{
        {0,0,1,0,0},
        {0,1,2,1,0},
        {1,2,-16,2,1},
        {0,1,2,1,0},
        {0,0,1,0,0}
    };
    return kernel;
}

matrix applyFilter(matrix image, kernel filter) {
    int height = image.size();
    int width = image[0].size();
    int filterHeight = filter.size();
    int filterWidth = filter[0].size();
    matrix newImage(height, vec(width));
    int kCenterX = filterHeight / 2;
    int kCenterY = filterWidth / 2;
    std::cout << "started convolution" << std::endl;
    for (int i = 0; i < height; ++i) {
        for (int j = 0; j < width; ++j) {
            double tmp = 0;
            for (int m = 0; m < filterHeight; ++m) {
                for (int n = 0; n < filterWidth; ++n) {
                    int ii = i + (kCenterY - m);
                    int jj = j + (kCenterX - n);
                    if (ii >= 0 && ii < height && jj >= 0 && jj < width)
                        tmp += image[ii][jj] * filter[m][n];
                }
            }
            if (tmp > 255) {
                tmp = 255;
            }
            else if (tmp < 0) {
                tmp = 0;
            }
            newImage[i][j] = (uint8_t)tmp;
        }
    }
    std::cout << "convolution done" << std::endl;
    return newImage;
}

matrix getImageByFileName(std::string filename, int row)
{
    vec rawFile = readFile(filename);
    matrix image = toMatrix(rawFile, row);
    return image;
}


int main(int argc, char * argv[])
{
    int row = atoi(argv[1]);
    int col = atoi(argv[2]);

    std::string outFile = "result" + std::string(argv[1]) + "_" + std::string(argv[2]) + ".bin";
    std::string inFile = "../labMPI/infile" + std::string(argv[1]) + "_" + std::string(argv[2]) + ".bin";

    matrix inImage = getImageByFileName(inFile, row);
    std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
    matrix newImage = applyFilter(inImage, getLogKernel());
    std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::seconds>(t2 - t1).count();
    std::cout << duration << "s " << std::endl;
    saveImage(outFile, newImage);

    return 0;
}

Исходное изображение: input.bin

Результат, который я получаю: output.bin

Результат, который я получил с помощью перевернутой строки / столбца при чтении изображения: correctoutput.bin Сохранение изображения без обработки дает то же самое изображение, что и ввод, поэтому я пришел к выводу, что сохранение работает нормально.

1 Ответ

0 голосов
/ 06 января 2019

Полагаю, вам нужно прочитать изображение с замененными размерами, поэтому смещение высоты на ширину должно работать.

...