Реализация фильтров
This commit is contained in:
parent
24e2cbb354
commit
3fe2a87e35
4 changed files with 109 additions and 58 deletions
86
bmpimage.cpp
86
bmpimage.cpp
|
@ -1,4 +1,6 @@
|
|||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include "bmpimage.h"
|
||||
|
||||
BMPImage::BMPImage(const BitmapFileHeader &fileHeader, const BITMAPINFOHEADER &infoHeader, const PixelArray &pixelArray)
|
||||
|
@ -83,6 +85,7 @@ BMPImage BMPImage::appendRight(BMPImage &img) {
|
|||
uint32_t newWidth = this->infoHeader.BitmapWidth + img.width();
|
||||
// Pixel **newPixelArray;
|
||||
PixelArray newPixelArray(newWidth, newHeight);
|
||||
// std::shared_ptr<PixelArray> newPixelArray = std::make_shared<PixelArray>(newWidth, newHeight);
|
||||
// newPixelArray = new Pixel *[newHeight];
|
||||
for (int i = 0; i < this->infoHeader.BitmapHeight; ++i) {
|
||||
// newPixelArray[i] = new Pixel[newWidth];
|
||||
|
@ -105,6 +108,32 @@ BMPImage BMPImage::overlay(BMPImage &img, uint32_t pos_x, uint32_t pos_y) {
|
|||
return {pixels};
|
||||
}
|
||||
|
||||
BMPImage BMPImage::applyFilter(const std::function<uint8_t(std::array<int, 9> &)> &filter) {
|
||||
auto origPixels = this->pixels_copy();
|
||||
PixelArray pixels(this->width(), this->height());
|
||||
for (int y = 1; y < this->height() - 1; ++y) {
|
||||
for (int x = 1; x < this->width() - 1; ++x) {
|
||||
auto p1 = origPixels(y - 1, x - 1);
|
||||
auto p2 = origPixels(y - 1, x);
|
||||
auto p3 = origPixels(y - 1, x + 1);
|
||||
auto p4 = origPixels(y, x - 1);
|
||||
auto p5 = origPixels(y, x);
|
||||
auto p6 = origPixels(y, x + 1);
|
||||
auto p7 = origPixels(y + 1, x - 1);
|
||||
auto p8 = origPixels(y + 1, x);
|
||||
auto p9 = origPixels(y + 1, x + 1);
|
||||
std::array<int, 9> red_channel = {p1.r, p2.r, p3.r, p4.r, p5.r, p6.r, p7.r, p8.r, p9.r};
|
||||
std::array<int, 9> green_channel = {p1.g, p2.g, p3.g, p4.g, p5.g, p6.g, p7.g, p8.g, p9.g};
|
||||
std::array<int, 9> blue_channel = {p1.b, p2.b, p3.b, p4.b, p5.b, p6.b, p7.b, p8.b, p9.b};
|
||||
auto r = filter(red_channel);
|
||||
auto g = filter(green_channel);
|
||||
auto b = filter(blue_channel);
|
||||
pixels(y, x) = {r, g, b};
|
||||
}
|
||||
}
|
||||
return {pixels};
|
||||
}
|
||||
|
||||
|
||||
BMPImage readBMPImage(const std::string &filename) {
|
||||
BitmapFileHeader bitmapFileHeader;
|
||||
|
@ -405,30 +434,39 @@ BMPImage upscale2x_ver2(BMPImage &img) {
|
|||
return {newPixelArray};
|
||||
}
|
||||
|
||||
BMPImage filter(BMPImage &img, int mask[9], uint8_t modifier) {
|
||||
auto origPixels = img.pixels_copy();
|
||||
PixelArray pixels(img.width(), img.height());
|
||||
for (int y = 1; y < img.height() - 1; ++y) {
|
||||
for (int x = 1; x < img.width() - 1; ++x) {
|
||||
auto p1 = origPixels(y - 1, x - 1);
|
||||
auto p2 = origPixels(y - 1, x);
|
||||
auto p3 = origPixels(y - 1, x + 1);
|
||||
auto p4 = origPixels(y, x - 1);
|
||||
auto p5 = origPixels(y, x);
|
||||
auto p6 = origPixels(y, x + 1);
|
||||
auto p7 = origPixels(y + 1, x - 1);
|
||||
auto p8 = origPixels(y + 1, x);
|
||||
auto p9 = origPixels(y + 1, x + 1);
|
||||
auto r = p1.r * mask[0] + p2.r * mask[1] + p3.r * mask[2] + p4.r * mask[3] + p5.r * mask[4] +
|
||||
p6.r * mask[5] + p7.r * mask[6] + p8.r * mask[7] + p9.r * mask[8];
|
||||
auto g = p1.g * mask[0] + p2.g * mask[1] + p3.g * mask[2] + p4.g * mask[3] + p5.g * mask[4] +
|
||||
p6.g * mask[5] + p7.g * mask[6] + p8.g * mask[7] + p9.g * mask[8];
|
||||
auto b = p1.b * mask[0] + p2.b * mask[1] + p3.b * mask[2] + p4.b * mask[3] + p5.b * mask[4] +
|
||||
p6.b * mask[5] + p7.b * mask[6] + p8.b * mask[7] + p9.b * mask[8];
|
||||
pixels(y, x) = {ui8_clamp(r / modifier), ui8_clamp(g / modifier), ui8_clamp(b / modifier)};
|
||||
}
|
||||
}
|
||||
return {pixels};
|
||||
uint8_t medianFilter(std::array<int, 9> &pixels) {
|
||||
std::sort(pixels.begin(), pixels.end());
|
||||
return ui8_clamp(pixels[5]);
|
||||
}
|
||||
|
||||
uint8_t averageFilter(std::array<int, 9> &pixels) {
|
||||
return ui8_clamp((pixels[0] * AVERAGE_MASK[0] + pixels[1] * AVERAGE_MASK[1] + pixels[2] * AVERAGE_MASK[2] +
|
||||
pixels[3] * AVERAGE_MASK[3] + pixels[4] * AVERAGE_MASK[4] + pixels[5] * AVERAGE_MASK[5] +
|
||||
pixels[6] * AVERAGE_MASK[6] + pixels[7] * AVERAGE_MASK[7] + pixels[8] * AVERAGE_MASK[8]) / 9);
|
||||
}
|
||||
|
||||
uint8_t prewittDXFilter(std::array<int, 9> &pixels) {
|
||||
return ui8_clamp(pixels[0] * PREWITT_MASK_DX[0] + pixels[1] * PREWITT_MASK_DX[1] + pixels[2] * PREWITT_MASK_DX[2] +
|
||||
pixels[3] * PREWITT_MASK_DX[3] + pixels[4] * PREWITT_MASK_DX[4] + pixels[5] * PREWITT_MASK_DX[5] +
|
||||
pixels[6] * PREWITT_MASK_DX[6] + pixels[7] * PREWITT_MASK_DX[7] + pixels[8] * PREWITT_MASK_DX[8]);
|
||||
}
|
||||
|
||||
uint8_t prewittDYFilter(std::array<int, 9> &pixels) {
|
||||
return ui8_clamp(pixels[0] * PREWITT_MASK_DY[0] + pixels[1] * PREWITT_MASK_DY[1] + pixels[2] * PREWITT_MASK_DY[2] +
|
||||
pixels[3] * PREWITT_MASK_DY[3] + pixels[4] * PREWITT_MASK_DY[4] + pixels[5] * PREWITT_MASK_DY[5] +
|
||||
pixels[6] * PREWITT_MASK_DY[6] + pixels[7] * PREWITT_MASK_DY[7] + pixels[8] * PREWITT_MASK_DY[8]);
|
||||
}
|
||||
|
||||
uint8_t sobelDXFilter(std::array<int, 9> &pixels) {
|
||||
return ui8_clamp(pixels[0] * SOBEL_MASK_DX[0] + pixels[1] * SOBEL_MASK_DX[1] + pixels[2] * SOBEL_MASK_DX[2] +
|
||||
pixels[3] * SOBEL_MASK_DX[3] + pixels[4] * SOBEL_MASK_DX[4] + pixels[5] * SOBEL_MASK_DX[5] +
|
||||
pixels[6] * SOBEL_MASK_DX[6] + pixels[7] * SOBEL_MASK_DX[7] + pixels[8] * SOBEL_MASK_DX[8]);
|
||||
}
|
||||
|
||||
uint8_t sobelDYFilter(std::array<int, 9> &pixels) {
|
||||
return ui8_clamp(pixels[0] * SOBEL_MASK_DY[0] + pixels[1] * SOBEL_MASK_DY[1] + pixels[2] * SOBEL_MASK_DY[2] +
|
||||
pixels[3] * SOBEL_MASK_DY[3] + pixels[4] * SOBEL_MASK_DY[4] + pixels[5] * SOBEL_MASK_DY[5] +
|
||||
pixels[6] * SOBEL_MASK_DY[6] + pixels[7] * SOBEL_MASK_DY[7] + pixels[8] * SOBEL_MASK_DY[8]);
|
||||
}
|
||||
|
||||
PixelArray::PixelArray(uint32_t width, uint32_t height) {
|
||||
|
|
22
bmpimage.h
22
bmpimage.h
|
@ -3,9 +3,17 @@
|
|||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include "psf.h"
|
||||
|
||||
const char PADDING_ZEROES[3] = {0, 0, 0};
|
||||
const int AVERAGE_MASK[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
const int PREWITT_MASK_DX[9] = {-1, 0, 1, -1, 0, 1, -1, 0, 1};
|
||||
const int PREWITT_MASK_DY[9] = {-1, -1, -1, 0, 0, 0, 1, 1, 1};
|
||||
const int SOBEL_MASK_DX[9] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
|
||||
const int SOBEL_MASK_DY[9] = {-1, -2, -1, 0, 0, 0, 1, 2, 1};
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct BitmapFileHeader {
|
||||
|
@ -91,6 +99,8 @@ public:
|
|||
BMPImage appendRight(BMPImage &);
|
||||
|
||||
BMPImage overlay(BMPImage &, uint32_t, uint32_t);
|
||||
|
||||
BMPImage applyFilter(const std::function<uint8_t (std::array<int,9>&)>& filter);
|
||||
};
|
||||
|
||||
BMPImage readBMPImage(const std::string &filename);
|
||||
|
@ -126,4 +136,14 @@ BMPImage textImg(const std::u16string &, Font *font, uint8_t scale = 1, Pixel ba
|
|||
|
||||
uint8_t ui8_clamp(int value, uint8_t min = 0, uint8_t max = 255);
|
||||
|
||||
BMPImage filter(BMPImage &img, int mask[9], uint8_t modifier = 9);
|
||||
uint8_t medianFilter(std::array<int, 9> &);
|
||||
|
||||
uint8_t averageFilter(std::array<int, 9> &);
|
||||
|
||||
uint8_t prewittDXFilter(std::array<int, 9> &);
|
||||
|
||||
uint8_t prewittDYFilter(std::array<int, 9> &);
|
||||
|
||||
uint8_t sobelDXFilter(std::array<int, 9> &);
|
||||
|
||||
uint8_t sobelDYFilter(std::array<int, 9> &);
|
57
main.cpp
57
main.cpp
|
@ -2,11 +2,8 @@
|
|||
#include "bmpimage.h"
|
||||
#include "psf.h"
|
||||
|
||||
const std::string FILENAME = "../elef.bmp";
|
||||
const std::string FILENAME_OUT = "../elef_out.bmp";
|
||||
auto font = readPSF("../fonts/ruscii_8x16_2.psf");
|
||||
|
||||
//
|
||||
void lab01() {
|
||||
auto og_image = readBMPImage("../elef.bmp");
|
||||
auto pixels1 = og_image.pixels_copy();
|
||||
|
@ -31,7 +28,6 @@ void lab01() {
|
|||
orig_text, 0, 0).save("../lab01/elef1.bmp");
|
||||
}
|
||||
|
||||
//
|
||||
void lab02_01() {
|
||||
auto img = readBMPImage("../tea.bmp");
|
||||
auto text1024 = textImg(u"1024", &font, 3);
|
||||
|
@ -63,7 +59,6 @@ void lab02_01() {
|
|||
// newImg2->save("../lab02/tea_upscale.bmp");
|
||||
}
|
||||
|
||||
//
|
||||
void lab02_02() {
|
||||
auto img = readBMPImage("../tea.bmp");
|
||||
auto ogText = textImg(u"Оригинал", &font, 3);
|
||||
|
@ -103,7 +98,6 @@ void lab02_02() {
|
|||
gsImg64).appendRight(gsImg32).save("../lab02/tea_grayscale.bmp");
|
||||
}
|
||||
|
||||
//
|
||||
void lab02_03() {
|
||||
auto img = readBMPImage("../tea.bmp");
|
||||
auto text = textImg(u"Оригинал", &font, 3);
|
||||
|
@ -134,40 +128,39 @@ void lab02_03() {
|
|||
}
|
||||
|
||||
void lab03() {
|
||||
auto img = readBMPImage("../tea.bmp");
|
||||
auto img = readBMPImage("../bike.bmp");
|
||||
auto imgGS = grayscale(img);
|
||||
int avrg_mask[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
int previtt_mask1[9] = {-1, 0, 1, -1, 0, 1, -1, 0, 1};
|
||||
int previtt_mask2[9] = {-1, -1, -1, 0, 0, 0, 1, 1, 1};
|
||||
int sobel_mask1[9] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
|
||||
int sobel_mask2[9] = {-1, -2, -1, 0, 0, 0, 1, 2, 1};
|
||||
|
||||
auto avrg_text = textImg(u"Осреднение", &font, 3);
|
||||
auto previtt_text = textImg(u"Фильтр Превитта", &font, 3);
|
||||
auto median_text = textImg(u"Медиана", &font, 3);
|
||||
auto prewitt_text = textImg(u"Фильтр Превитта", &font, 3);
|
||||
auto sobel_text = textImg(u"Фильтр Собеля", &font, 3);
|
||||
auto text = textImg(u"Оригинал", &font, 3);
|
||||
auto avrg_image = filter(imgGS, avrg_mask).overlay(avrg_text, 0, 0);
|
||||
auto previtt_image1 = filter(imgGS, previtt_mask1, 1);//.overlay(previtt_text, 0, 0);
|
||||
auto previtt_image2 = filter(imgGS, previtt_mask2, 1);//.overlay(previtt_text, 0, 0);
|
||||
previtt_image1.save("../lab03/previtt1.bmp");
|
||||
previtt_image2.save("../lab03/previtt2.bmp");
|
||||
PixelArray previttPixels(previtt_image1.width(), previtt_image1.height());
|
||||
for (int y = 0; y < previtt_image1.height(); ++y) {
|
||||
for (int x = 0; x < previtt_image1.width(); ++x) {
|
||||
previttPixels(y, x) = previtt_image1.pixels()(y, x) + previtt_image2.pixels()(y, x);
|
||||
|
||||
auto avrg_image = imgGS.applyFilter(averageFilter).overlay(avrg_text, 0, 0);
|
||||
auto median_image = imgGS.applyFilter(medianFilter).overlay(median_text, 0, 0);
|
||||
auto prewitt_dx_image = imgGS.applyFilter(prewittDXFilter);
|
||||
auto prewitt_dy_image = imgGS.applyFilter(prewittDYFilter);
|
||||
prewitt_dx_image.save("../lab03/prewitt1.bmp");
|
||||
prewitt_dy_image.save("../lab03/prewitt2.bmp");
|
||||
PixelArray prewittPixels(prewitt_dx_image.width(), prewitt_dy_image.height());
|
||||
for (int y = 0; y < prewitt_dx_image.height(); ++y) {
|
||||
for (int x = 0; x < prewitt_dx_image.width(); ++x) {
|
||||
prewittPixels(y, x) = prewitt_dx_image.pixels()(y, x) + prewitt_dy_image.pixels()(y, x);
|
||||
}
|
||||
}
|
||||
auto previtt_image = BMPImage(previttPixels).overlay(previtt_text, 0, 0);
|
||||
auto sobel_image1 = filter(imgGS, sobel_mask1, 1).overlay(sobel_text, 0, 0);
|
||||
auto sobel_image2 = filter(imgGS, sobel_mask2, 1).overlay(sobel_text, 0, 0);
|
||||
PixelArray sobelPixels(sobel_image1.width(), sobel_image2.height());
|
||||
for (int y = 0; y < sobel_image1.height(); ++y) {
|
||||
for (int x = 0; x < sobel_image1.width(); ++x) {
|
||||
previttPixels(y, x) = sobel_image1.pixels()(y, x) + sobel_image2.pixels()(y, x);
|
||||
auto prewitt_image = BMPImage(prewittPixels).overlay(prewitt_text, 0, 0);
|
||||
auto sobel_dx_image = imgGS.applyFilter(sobelDXFilter).overlay(sobel_text, 0, 0);
|
||||
auto sobel_dy_image2 = imgGS.applyFilter(sobelDYFilter).overlay(sobel_text, 0, 0);
|
||||
PixelArray sobelPixels(sobel_dx_image.width(), sobel_dx_image.height());
|
||||
for (int y = 0; y < sobel_dx_image.height(); ++y) {
|
||||
for (int x = 0; x < sobel_dx_image.width(); ++x) {
|
||||
sobelPixels(y, x) = sobel_dx_image.pixels()(y, x) + sobel_dy_image2.pixels()(y, x);
|
||||
}
|
||||
}
|
||||
auto sobel_image = BMPImage(previttPixels).overlay(sobel_text, 0, 0);
|
||||
imgGS.overlay(text, 0, 0).appendRight(avrg_image).save("../lab03/avrg_filter.bmp");
|
||||
imgGS.overlay(text, 0, 0).appendRight(previtt_image).save("../lab03/previtt_filter.bmp");
|
||||
auto sobel_image = BMPImage(sobelPixels).overlay(sobel_text, 0, 0);
|
||||
imgGS.overlay(text, 0, 0).appendRight(avrg_image).appendRight(median_image).save("../lab03/avrg_median_filter.bmp");
|
||||
imgGS.overlay(text, 0, 0).appendRight(prewitt_image).save("../lab03/prewitt_filter.bmp");
|
||||
imgGS.overlay(text, 0, 0).appendRight(sobel_image).save("../lab03/sobel_filter.bmp");
|
||||
}
|
||||
|
||||
|
|
2
psf.cpp
2
psf.cpp
|
@ -49,7 +49,7 @@ Font readPSF(const std::string &filename) {
|
|||
if (curByte != 0xFF) {
|
||||
vectorOfBytes.push_back(curByte);
|
||||
} else {
|
||||
unsigned long long int bytesCount = vectorOfBytes.size();
|
||||
auto bytesCount = vectorOfBytes.size();
|
||||
unsigned char bytes[bytesCount];
|
||||
for (int i = 0; i < bytesCount; ++i) {
|
||||
bytes[i] = vectorOfBytes[i];
|
||||
|
|
Loading…
Add table
Reference in a new issue