圖片處理與濾鏡的C++實現(xiàn)

圖片處理與濾鏡的C++實現(xiàn)

1. 基礎(chǔ)圖像類定義

<cpp>

#include <vector>#include <cmath>#include <algorithm>#include <cstring>// 像素結(jié)構(gòu)體struct Pixel {? ? unsigned char r, g, b, a;? ? ? ? Pixel(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, unsigned char a = 255)? ? ? ? : r(r), g(g), b(b), a(a) {}};// 圖像類class Image {private:? ? int width, height;? ? std::vector<Pixel> pixels;? ? public:? ? Image(int w, int h) : width(w), height(h), pixels(w * h) {}? ? ? ? // 獲取像素? ? Pixel& getPixel(int x, int y) {? ? ? ? return pixels[y * width + x];? ? }? ? ? ? const Pixel& getPixel(int x, int y) const {? ? ? ? return pixels[y * width + x];? ? }? ? ? ? // 設(shè)置像素? ? void setPixel(int x, int y, const Pixel& p) {? ? ? ? if (x >= 0 && x < width && y >= 0 && y < height) {? ? ? ? ? ? pixels[y * width + x] = p;? ? ? ? }? ? }? ? ? ? int getWidth() const { return width; }? ? int getHeight() const { return height; }? ? ? ? // 克隆圖像? ? Image clone() const {? ? ? ? Image newImage(width, height);? ? ? ? newImage.pixels = pixels;? ? ? ? return newImage;? ? }};

2. 基礎(chǔ)圖像處理操作

2.1 亮度調(diào)整

<cpp>

class BrightnessFilter {public:? ? // 調(diào)整亮度 (-100 到 100)? ? static void adjustBrightness(Image& image, int brightness) {? ? ? ? for (int y = 0; y < image.getHeight(); y++) {? ? ? ? ? ? for (int x = 0; x < image.getWidth(); x++) {? ? ? ? ? ? ? ? Pixel p = image.getPixel(x, y);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? p.r = clamp(p.r + brightness, 0, 255);? ? ? ? ? ? ? ? p.g = clamp(p.g + brightness, 0, 255);? ? ? ? ? ? ? ? p.b = clamp(p.b + brightness, 0, 255);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? image.setPixel(x, y, p);? ? ? ? ? ? }? ? ? ? }? ? }? ? private:? ? static int clamp(int value, int min, int max) {? ? ? ? return std::max(min, std::min(max, value));? ? }};

2.2 對比度調(diào)整

<cpp>

class ContrastFilter {public:? ? // 調(diào)整對比度 (-100 到 100)? ? static void adjustContrast(Image& image, float contrast) {? ? ? ? float factor = (259.0f * (contrast + 255.0f)) / (255.0f * (259.0f - contrast));? ? ? ? ? ? ? ? for (int y = 0; y < image.getHeight(); y++) {? ? ? ? ? ? for (int x = 0; x < image.getWidth(); x++) {? ? ? ? ? ? ? ? Pixel p = image.getPixel(x, y);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? p.r = clamp(factor * (p.r - 128) + 128);? ? ? ? ? ? ? ? p.g = clamp(factor * (p.g - 128) + 128);? ? ? ? ? ? ? ? p.b = clamp(factor * (p.b - 128) + 128);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? image.setPixel(x, y, p);? ? ? ? ? ? }? ? ? ? }? ? }? ? private:? ? static int clamp(float value) {? ? ? ? return std::max(0, std::min(255, (int)value));? ? }};

2.3 飽和度調(diào)整

<cpp>

class SaturationFilter {public:? ? // 調(diào)整飽和度 (0.0 到 2.0, 1.0為原始)? ? static void adjustSaturation(Image& image, float saturation) {? ? ? ? for (int y = 0; y < image.getHeight(); y++) {? ? ? ? ? ? for (int x = 0; x < image.getWidth(); x++) {? ? ? ? ? ? ? ? Pixel p = image.getPixel(x, y);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 轉(zhuǎn)換到HSL空間? ? ? ? ? ? ? ? float h, s, l;? ? ? ? ? ? ? ? rgbToHsl(p.r / 255.0f, p.g / 255.0f, p.b / 255.0f, h, s, l);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 調(diào)整飽和度? ? ? ? ? ? ? ? s *= saturation;? ? ? ? ? ? ? ? s = std::min(1.0f, s);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 轉(zhuǎn)換回RGB? ? ? ? ? ? ? ? float r, g, b;? ? ? ? ? ? ? ? hslToRgb(h, s, l, r, g, b);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? p.r = r * 255;? ? ? ? ? ? ? ? p.g = g * 255;? ? ? ? ? ? ? ? p.b = b * 255;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? image.setPixel(x, y, p);? ? ? ? ? ? }? ? ? ? }? ? }? ? private:? ? static void rgbToHsl(float r, float g, float b, float& h, float& s, float& l) {? ? ? ? float max = std::max({r, g, b});? ? ? ? float min = std::min({r, g, b});? ? ? ? ? ? ? ? l = (max + min) / 2.0f;? ? ? ? ? ? ? ? if (max == min) {? ? ? ? ? ? h = s = 0; // achromatic? ? ? ? } else {? ? ? ? ? ? float d = max - min;? ? ? ? ? ? s = l > 0.5f ? d / (2.0f - max - min) : d / (max + min);? ? ? ? ? ? ? ? ? ? ? ? if (max == r) {? ? ? ? ? ? ? ? h = (g - b) / d + (g < b ? 6.0f : 0.0f);? ? ? ? ? ? } else if (max == g) {? ? ? ? ? ? ? ? h = (b - r) / d + 2.0f;? ? ? ? ? ? } else {? ? ? ? ? ? ? ? h = (r - g) / d + 4.0f;? ? ? ? ? ? }? ? ? ? ? ? h /= 6.0f;? ? ? ? }? ? }? ? ? ? static void hslToRgb(float h, float s, float l, float& r, float& g, float& b) {? ? ? ? if (s == 0) {? ? ? ? ? ? r = g = b = l; // achromatic? ? ? ? } else {? ? ? ? ? ? auto hue2rgb = [](float p, float q, float t) {? ? ? ? ? ? ? ? if (t < 0) t += 1;? ? ? ? ? ? ? ? if (t > 1) t -= 1;? ? ? ? ? ? ? ? if (t < 1.0f/6.0f) return p + (q - p) * 6.0f * t;? ? ? ? ? ? ? ? if (t < 1.0f/2.0f) return q;? ? ? ? ? ? ? ? if (t < 2.0f/3.0f) return p + (q - p) * (2.0f/3.0f - t) * 6.0f;? ? ? ? ? ? ? ? return p;? ? ? ? ? ? };? ? ? ? ? ? ? ? ? ? ? ? float q = l < 0.5f ? l * (1.0f + s) : l + s - l * s;? ? ? ? ? ? float p = 2.0f * l - q;? ? ? ? ? ? ? ? ? ? ? ? r = hue2rgb(p, q, h + 1.0f/3.0f);? ? ? ? ? ? g = hue2rgb(p, q, h);? ? ? ? ? ? b = hue2rgb(p, q, h - 1.0f/3.0f);? ? ? ? }? ? }};

3. 模糊濾鏡

3.1 高斯模糊

<cpp>

class GaussianBlur {public:? ? static void apply(Image& image, float sigma) {? ? ? ? int kernelSize = (int)(sigma * 6) | 1; // 確保是奇數(shù)? ? ? ? std::vector<float> kernel = createGaussianKernel(kernelSize, sigma);? ? ? ? ? ? ? ? Image temp = image.clone();? ? ? ? ? ? ? ? // 水平方向模糊? ? ? ? for (int y = 0; y < image.getHeight(); y++) {? ? ? ? ? ? for (int x = 0; x < image.getWidth(); x++) {? ? ? ? ? ? ? ? applyKernelHorizontal(image, temp, x, y, kernel);? ? ? ? ? ? }? ? ? ? }? ? ? ? ? ? ? ? // 垂直方向模糊? ? ? ? image = temp;? ? ? ? temp = image.clone();? ? ? ? ? ? ? ? for (int y = 0; y < image.getHeight(); y++) {? ? ? ? ? ? for (int x = 0; x < image.getWidth(); x++) {? ? ? ? ? ? ? ? applyKernelVertical(image, temp, x, y, kernel);? ? ? ? ? ? }? ? ? ? }? ? ? ? ? ? ? ? image = temp;? ? }? ? private:? ? static std::vector<float> createGaussianKernel(int size, float sigma) {? ? ? ? std::vector<float> kernel(size);? ? ? ? float sum = 0.0f;? ? ? ? int half = size / 2;? ? ? ? ? ? ? ? for (int i = 0; i < size; i++) {? ? ? ? ? ? float x = i - half;? ? ? ? ? ? kernel[i] = exp(-(x * x) / (2.0f * sigma * sigma));? ? ? ? ? ? sum += kernel[i];? ? ? ? }? ? ? ? ? ? ? ? // 歸一化? ? ? ? for (int i = 0; i < size; i++) {? ? ? ? ? ? kernel[i] /= sum;? ? ? ? }? ? ? ? ? ? ? ? return kernel;? ? }? ? ? ? static void applyKernelHorizontal(const Image& src, Image& dst, int x, int y,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const std::vector<float>& kernel) {? ? ? ? int half = kernel.size() / 2;? ? ? ? float r = 0, g = 0, b = 0;? ? ? ? ? ? ? ? for (int i = 0; i < kernel.size(); i++) {? ? ? ? ? ? int sx = x + i - half;? ? ? ? ? ? sx = std::max(0, std::min(src.getWidth() - 1, sx));? ? ? ? ? ? ? ? ? ? ? ? Pixel p = src.getPixel(sx, y);? ? ? ? ? ? r += p.r * kernel[i];? ? ? ? ? ? g += p.g * kernel[i];? ? ? ? ? ? b += p.b * kernel[i];? ? ? ? }? ? ? ? ? ? ? ? dst.setPixel(x, y, Pixel(r, g, b));? ? }? ? ? ? static void applyKernelVertical(const Image& src, Image& dst, int x, int y,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const std::vector<float>& kernel) {? ? ? ? int half = kernel.size() / 2;? ? ? ? float r = 0, g = 0, b = 0;? ? ? ? ? ? ? ? for (int i = 0; i < kernel.size(); i++) {? ? ? ? ? ? int sy = y + i - half;? ? ? ? ? ? sy = std::max(0, std::min(src.getHeight() - 1, sy));? ? ? ? ? ? ? ? ? ? ? ? Pixel p = src.getPixel(x, sy);? ? ? ? ? ? r += p.r * kernel[i];? ? ? ? ? ? g += p.g * kernel[i];? ? ? ? ? ? b += p.b * kernel[i];? ? ? ? }? ? ? ? ? ? ? ? dst.setPixel(x, y, Pixel(r, g, b));? ? }};

3.2 運動模糊

<cpp>

class MotionBlur {public:? ? static void apply(Image& image, int angle, int distance) {? ? ? ? Image result = image.clone();? ? ? ? float rad = angle * M_PI / 180.0f;? ? ? ? float dx = cos(rad);? ? ? ? float dy = sin(rad);? ? ? ? ? ? ? ? for (int y = 0; y < image.getHeight(); y++) {? ? ? ? ? ? for (int x = 0; x < image.getWidth(); x++) {? ? ? ? ? ? ? ? float r = 0, g = 0, b = 0;? ? ? ? ? ? ? ? int count = 0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? for (int i = 0; i < distance; i++) {? ? ? ? ? ? ? ? ? ? int sx = x + (int)(dx * i);? ? ? ? ? ? ? ? ? ? int sy = y + (int)(dy * i);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (sx >= 0 && sx < image.getWidth() &&? ? ? ? ? ? ? ? ? ? ? ? sy >= 0 && sy < image.getHeight()) {? ? ? ? ? ? ? ? ? ? ? ? Pixel p = image.getPixel(sx, sy);? ? ? ? ? ? ? ? ? ? ? ? r += p.r;? ? ? ? ? ? ? ? ? ? ? ? g += p.g;? ? ? ? ? ? ? ? ? ? ? ? b += p.b;? ? ? ? ? ? ? ? ? ? ? ? count++;? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (count > 0) {? ? ? ? ? ? ? ? ? ? result.setPixel(x, y, Pixel(r/count, g/count, b/count));? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }? ? ? ? ? ? ? ? image = result;? ? }};

4. 銳化濾鏡

<cpp>

class SharpenFilter {public:? ? static void apply(Image& image, float strength = 1.0f) {? ? ? ? // 銳化卷積核? ? ? ? float kernel[3][3] = {? ? ? ? ? ? {0, -1, 0},? ? ? ? ? ? {-1, 5, -1},? ? ? ? ? ? {0, -1, 0}? ? ? ? };? ? ? ? ? ? ? ? // 調(diào)整強度? ? ? ? float center = 1 + 4 * strength;? ? ? ? kernel[1][1] = center;? ? ? ? for (int i = 0; i < 3; i++) {? ? ? ? ? ? for (int j = 0; j < 3; j++) {? ? ? ? ? ? ? ? if (i != 1 || j != 1) {? ? ? ? ? ? ? ? ? ? kernel[i][j] *= strength;? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }? ? ? ? ? ? ? ? Image result = image.clone();? ? ? ? ? ? ? ? for (int y = 1; y < image.getHeight() - 1; y++) {? ? ? ? ? ? for (int x = 1; x < image.getWidth() - 1; x++) {? ? ? ? ? ? ? ? float r = 0, g = 0, b = 0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? for (int ky = -1; ky <= 1; ky++) {? ? ? ? ? ? ? ? ? ? for (int kx = -1; kx <= 1; kx++) {? ? ? ? ? ? ? ? ? ? ? ? Pixel p = image.getPixel(x + kx, y + ky);? ? ? ? ? ? ? ? ? ? ? ? float weight = kernel[ky + 1][kx + 1];? ? ? ? ? ? ? ? ? ? ? ? r += p.r * weight;? ? ? ? ? ? ? ? ? ? ? ? g += p.g * weight;? ? ? ? ? ? ? ? ? ? ? ? b += p.b * weight;? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result.setPixel(x, y, Pixel(? ? ? ? ? ? ? ? ? ? std::max(0, std::min(255, (int)r)),? ? ? ? ? ? ? ? ? ? std::max(0, std::min(255, (int)g)),? ? ? ? ? ? ? ? ? ? std::max(0, std::min(255, (int)b))? ? ? ? ? ? ? ? ));? ? ? ? ? ? }? ? ? ? }? ? ? ? ? ? ? ? image = result;? ? }};

5. 邊緣檢測

<cpp>

class EdgeDetection {public:? ? // Sobel邊緣檢測? ? static void sobelEdgeDetection(Image& image) {? ? ? ? int sobelX[3][3] = {? ? ? ? ? ? {-1, 0, 1},? ? ? ? ? ? {-2, 0, 2},? ? ? ? ? ? {-1, 0, 1}? ? ? ? };? ? ? ? ? ? ? ? int sobelY[3][3] = {? ? ? ? ? ? {-1, -2, -1},? ? ? ? ? ? {0, 0, 0},? ? ? ? ? ? {1, 2, 1}? ? ? ? };? ? ? ? ? ? ? ? Image result = image.clone();? ? ? ? ? ? ? ? for (int y = 1; y < image.getHeight() - 1; y++) {? ? ? ? ? ? for (int x = 1; x < image.getWidth() - 1; x++) {? ? ? ? ? ? ? ? int gx = 0, gy = 0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 計算梯度? ? ? ? ? ? ? ? for (int ky = -1; ky <= 1; ky++) {? ? ? ? ? ? ? ? ? ? for (int kx = -1; kx <= 1; kx++) {? ? ? ? ? ? ? ? ? ? ? ? Pixel p = image.getPixel(x + kx, y + ky);? ? ? ? ? ? ? ? ? ? ? ? int gray = (p.r + p.g + p.b) / 3;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? gx += gray * sobelX[ky + 1][kx + 1];? ? ? ? ? ? ? ? ? ? ? ? gy += gray * sobelY[ky + 1][kx + 1];? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int magnitude = sqrt(gx * gx + gy * gy);? ? ? ? ? ? ? ? magnitude = std::min(255, magnitude);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result.setPixel(x, y, Pixel(magnitude, magnitude, magnitude));? ? ? ? ? ? }? ? ? ? }? ? ? ? ? ? ? ? image = result;? ? }? ? ? ? // Canny邊緣檢測? ? static void cannyEdgeDetection(Image& image, float lowThreshold, float highThreshold) {? ? ? ? // 1. 高斯模糊? ? ? ? GaussianBlur::apply(image, 1.4f);? ? ? ? ? ? ? ? // 2. 計算梯度? ? ? ? Image gradientMag(image.getWidth(), image.getHeight());? ? ? ? Image gradientDir(image.getWidth(), image.getHeight());? ? ? ? ? ? ? ? calculateGradients(image, gradientMag, gradientDir);? ? ? ? ? ? ? ? // 3. 非極大值抑制? ? ? ? Image suppressed = nonMaximumSuppression(gradientMag, gradientDir);? ? ? ? ? ? ? ? // 4. 雙閾值和邊緣連接? ? ? ? image = doubleThreshold(suppressed, lowThreshold, highThreshold);? ? }? ? private:? ? static void calculateGradients(const Image& image, Image& magnitude, Image& direction) {? ? ? ? for (int y = 1; y < image.getHeight() - 1; y++) {? ? ? ? ? ? for (int x = 1; x < image.getWidth() - 1; x++) {? ? ? ? ? ? ? ? // Sobel算子? ? ? ? ? ? ? ? int gx = 0, gy = 0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 簡化計算,只使用灰度? ? ? ? ? ? ? ? auto getGray = [&](int dx, int dy) {? ? ? ? ? ? ? ? ? ? Pixel p = image.getPixel(x + dx, y + dy);? ? ? ? ? ? ? ? ? ? return (p.r + p.g + p.b) / 3;? ? ? ? ? ? ? ? };? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? gx = -getGray(-1, -1) + getGray(1, -1) +? ? ? ? ? ? ? ? ? ? -2*getGray(-1, 0) + 2*getGray(1, 0) +? ? ? ? ? ? ? ? ? ? -getGray(-1, 1) + getGray(1, 1);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? gy = -getGray(-1, -1) - 2*getGray(0, -1) - getGray(1, -1) +? ? ? ? ? ? ? ? ? ? getGray(-1, 1) + 2*getGray(0, 1) + getGray(1, 1);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? float mag = sqrt(gx * gx + gy * gy);? ? ? ? ? ? ? ? float dir = atan2(gy, gx);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? magnitude.setPixel(x, y, Pixel(mag, mag, mag));? ? ? ? ? ? ? ? direction.setPixel(x, y, Pixel(dir * 255 / (2 * M_PI), 0, 0));? ? ? ? ? ? }? ? ? ? }? ? }? ? ? ? static Image nonMaximumSuppression(const Image& magnitude, const Image& direction) {? ? ? ? Image result(magnitude.getWidth(), magnitude.getHeight());? ? ? ? ? ? ? ? for (int y = 1; y < magnitude.getHeight() - 1; y++) {? ? ? ? ? ? for (int x = 1; x < magnitude.getWidth() - 1; x++) {? ? ? ? ? ? ? ? float angle = direction.getPixel(x, y).r * 2 * M_PI / 255;? ? ? ? ? ? ? ? float mag = magnitude.getPixel(x, y).r;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 將角度量化到4個方向? ? ? ? ? ? ? ? int dir = ((int)(angle / (M_PI / 4)) + 8) % 4;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? float mag1 = 0, mag2 = 0;? ? ? ? ? ? ? ? switch(dir) {? ? ? ? ? ? ? ? ? ? case 0: // 水平? ? ? ? ? ? ? ? ? ? ? ? mag1 = magnitude.getPixel(x-1, y).r;? ? ? ? ? ? ? ? ? ? ? ? mag2 = magnitude.getPixel(x+1, y).r;? ? ? ? ? ? ? ? ? ? ? ? break;? ? ? ? ? ? ? ? ? ? case 1: // 45度? ? ? ? ? ? ? ? ? ? ? ? mag1 = magnitude.getPixel(x-1, y-1).r;? ? ? ? ? ? ? ? ? ? ? ? mag2 = magnitude.getPixel(x+1, y+1).r;? ? ? ? ? ? ? ? ? ? ? ? break;? ? ? ? ? ? ? ? ? ? case 2: // 垂直? ? ? ? ? ? ? ? ? ? ? ? mag1 = magnitude.getPixel(x, y-1).r;? ? ? ? ? ? ? ? ? ? ? ? mag2 = magnitude.getPixel(x, y+1).r;? ? ? ? ? ? ? ? ? ? ? ? break;? ? ? ? ? ? ? ? ? ? case 3: // 135度? ? ? ? ? ? ? ? ? ? ? ? mag1 = magnitude.getPixel(x+1, y-1).r;? ? ? ? ? ? ? ? ? ? ? ? mag2 = magnitude.getPixel(x-1, y+1).r;? ? ? ? ? ? ? ? ? ? ? ? break;? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (mag >= mag1 && mag >= mag2) {? ? ? ? ? ? ? ? ? ? result.setPixel(x, y, Pixel(mag, mag, mag));? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }? ? ? ? ? ? ? ? return result;? ? }? ? ? ? static Image doubleThreshold(const Image& image, float low, float high) {? ? ? ? Image result(image.getWidth(), image.getHeight());? ? ? ? ? ? ? ? for (int y = 0; y < image.getHeight(); y++) {? ? ? ? ? ? for (int x = 0; x < image.getWidth(); x++) {? ? ? ? ? ? ? ? float val = image.getPixel(x, y).r;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (val >= high) {? ? ? ? ? ? ? ? ? ? result.setPixel(x, y, Pixel(255, 255, 255));? ? ? ? ? ? ? ? } else if (val >= low) {? ? ? ? ? ? ? ? ? ? result.setPixel(x, y, Pixel(128, 128, 128));? ? ? ? ? ? ? ? } else {? ? ? ? ? ? ? ? ? ? result.setPixel(x, y, Pixel(0, 0, 0));? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }? ? ? ? ? ? ? ? // 邊緣連接? ? ? ? for (int y = 1; y < result.getHeight() - 1; y++) {? ? ? ? ? ? for (int x = 1; x < result.getWidth() - 1; x++) {? ? ? ? ? ? ? ? if (result.getPixel(x, y).r == 128) {? ? ? ? ? ? ? ? ? ? bool hasStrongNeighbor = false;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? for (int dy = -1; dy <= 1; dy++) {? ? ? ? ? ? ? ? ? ? ? ? for (int dx = -1; dx <= 1; dx++) {? ? ? ? ? ? ? ? ? ? ? ? ? ? if (result.getPixel(x + dx, y + dy).r == 255) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? hasStrongNeighbor = true;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;? ? ? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (hasStrongNeighbor) {? ? ? ? ? ? ? ? ? ? ? ? result.setPixel(x, y, Pixel(255, 255, 255));? ? ? ? ? ? ? ? ? ? } else {? ? ? ? ? ? ? ? ? ? ? ? result.setPixel(x, y, Pixel(0, 0, 0));? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }? ? ? ? ? ? ? ? return result;? ? }};

6. 藝術(shù)濾鏡

6.1 素描效果

<cpp>

class SketchFilter {public:? ? static void apply(Image& image) {? ? ? ? // 1. 轉(zhuǎn)換為灰度圖? ? ? ? Image gray = toGrayscale(image);? ? ? ? ? ? ? ? // 2. 反色? ? ? ? Image inverted = invert(gray);? ? ? ? ? ? ? ? // 3. 高斯模糊? ? ? ? GaussianBlur::apply(inverted, 20.0f);? ? ? ? ? ? ? ? // 4. 顏色減淡混合? ? ? ? for (int y = 0; y < image.getHeight(); y++) {? ? ? ? ? ? for (int x = 0; x < image.getWidth(); x++) {? ? ? ? ? ? ? ? int gray_val = gray.getPixel(x, y).r;? ? ? ? ? ? ? ? int blur_val = inverted.getPixel(x, y).r;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int result = gray_val + (gray_val * blur_val) / (255 - blur_val + 1);? ? ? ? ? ? ? ? result = std::min(255, result);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? image.setPixel(x, y, Pixel(result, result, result));? ? ? ? ? ? }? ? ? ? }? ? }? ? private:? ? static Image toGrayscale(const Image& image) {? ? ? ? Image result(image.getWidth(), image.getHeight());? ? ? ? ? ? ? ? for (int y = 0; y < image.getHeight(); y++) {? ? ? ? ? ? for (int x = 0; x < image.getWidth(); x++) {? ? ? ? ? ? ? ? Pixel p = image.getPixel(x, y);? ? ? ? ? ? ? ? int gray = 0.299 * p.r + 0.587 * p.g + 0.114 * p.b;? ? ? ? ? ? ? ? result.setPixel(x, y, Pixel(gray, gray, gray));? ? ? ? ? ? }? ? ? ? }? ? ? ? ? ? ? ? return result;? ? }? ? ? ? static Image invert(const Image& image) {? ? ? ? Image result(image.getWidth(), image.getHeight());? ? ? ? ? ? ? ? for (int y = 0; y < image.getHeight(); y++) {? ? ? ? ? ? for (int x = 0; x < image.getWidth(); x++) {? ? ? ? ? ? ? ? Pixel p = image.getPixel(x, y);? ? ? ? ? ? ? ? result.setPixel(x, y, Pixel(255 - p.r, 255 - p.g, 255 - p.b));? ? ? ? ? ? }? ? ? ? }? ? ? ? ? ? ? ? return result;? ? }};

6.2 油畫效果

<cpp>

class OilPaintingFilter {public:? ? static void apply(Image& image, int radius = 4, int intensity = 20) {? ? ? ? Image result = image.clone();? ? ? ? ? ? ? ? for (int y = radius; y < image.getHeight() - radius; y++) {? ? ? ? ? ? for (int x = radius; x < image.getWidth() - radius; x++) {? ? ? ? ? ? ? ? std::vector<int> intensityCount(intensity + 1, 0);? ? ? ? ? ? ? ? std::vector<int> sumR(intensity + 1, 0);? ? ? ? ? ? ? ? std::vector<int> sumG(intensity + 1, 0);? ? ? ? ? ? ? ? std::vector<int> sumB(intensity + 1, 0);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 統(tǒng)計鄰域內(nèi)的顏色分布? ? ? ? ? ? ? ? for (int dy = -radius; dy <= radius; dy++) {? ? ? ? ? ? ? ? ? ? for (int dx = -radius; dx <= radius; dx++) {? ? ? ? ? ? ? ? ? ? ? ? Pixel p = image.getPixel(x + dx, y + dy);? ? ? ? ? ? ? ? ? ? ? ? int curIntensity = ((p.r + p.g + p.b) / 3) * intensity / 255;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? intensityCount[curIntensity]++;? ? ? ? ? ? ? ? ? ? ? ? sumR[curIntensity] += p.r;? ? ? ? ? ? ? ? ? ? ? ? sumG[curIntensity] += p.g;? ? ? ? ? ? ? ? ? ? ? ? sumB[curIntensity] += p.b;? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 找出出現(xiàn)最多的強度級別? ? ? ? ? ? ? ? int maxCount = 0;? ? ? ? ? ? ? ? int maxIndex = 0;? ? ? ? ? ? ? ? for (int i = 0; i <= intensity; i++) {? ? ? ? ? ? ? ? ? ? if (intensityCount[i] > maxCount) {? ? ? ? ? ? ? ? ? ? ? ? maxCount = intensityCount[i];? ? ? ? ? ? ? ? ? ? ? ? maxIndex = i;? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 使用該強度級別的平均顏色? ? ? ? ? ? ? ? if (maxCount > 0) {? ? ? ? ? ? ? ? ? ? result.setPixel(x, y, Pixel(? ? ? ? ? ? ? ? ? ? ? ? sumR[maxIndex] / maxCount,? ? ? ? ? ? ? ? ? ? ? ? sumG[maxIndex] / maxCount,? ? ? ? ? ? ? ? ? ? ? ? sumB[maxIndex] / maxCount? ? ? ? ? ? ? ? ? ? ));? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }? ? ? ? ? ? ? ? image = result;? ? }};

6.3 馬賽克效果

<cpp>

class MosaicFilter {public:? ? static void apply(Image& image, int blockSize = 10) {? ? ? ? for (int y = 0; y < image.getHeight(); y += blockSize) {? ? ? ? ? ? for (int x = 0; x < image.getWidth(); x += blockSize) {? ? ? ? ? ? ? ? // 計算塊的平均顏色? ? ? ? ? ? ? ? int sumR = 0, sumG = 0, sumB = 0;? ? ? ? ? ? ? ? int count = 0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? for (int dy = 0; dy < blockSize && y + dy < image.getHeight(); dy++) {? ? ? ? ? ? ? ? ? ? for (int dx = 0; dx < blockSize && x + dx < image.getWidth(); dx++) {? ? ? ? ? ? ? ? ? ? ? ? Pixel p = image.getPixel(x + dx, y + dy);? ? ? ? ? ? ? ? ? ? ? ? sumR += p.r;? ? ? ? ? ? ? ? ? ? ? ? sumG += p.g;? ? ? ? ? ? ? ? ? ? ? ? sumB += p.b;? ? ? ? ? ? ? ? ? ? ? ? count++;? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (count > 0) {? ? ? ? ? ? ? ? ? ? Pixel avgColor(sumR / count, sumG / count, sumB / count);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 填充整個塊? ? ? ? ? ? ? ? ? ? for (int dy = 0; dy < blockSize && y + dy < image.getHeight(); dy++) {? ? ? ? ? ? ? ? ? ? ? ? for (int dx = 0; dx < blockSize && x + dx < image.getWidth(); dx++) {? ? ? ? ? ? ? ? ? ? ? ? ? ? image.setPixel(x + dx, y + dy, avgColor);? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }? ? }};

7. 顏色濾鏡

7.1 復古濾鏡

<cpp>

class VintageFilter {public:? ? static void apply(Image& image) {? ? ? ? for (int y = 0; y < image.getHeight(); y++) {? ? ? ? ? ? for (int x = 0; x < image.getWidth(); x++) {? ? ? ? ? ? ? ? Pixel p = image.getPixel(x, y);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 應用復古色調(diào)映射? ? ? ? ? ? ? ? int r = (int)(0.393 * p.r + 0.769 * p.g + 0.189 * p.b);? ? ? ? ? ? ? ? int g = (int)(0.349 * p.r + 0.686 * p.g + 0.168 * p.b);? ? ? ? ? ? ? ? int b = (int)(0.272 * p.r + 0.534 * p.g + 0.131 * p.b);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? r = std::min(255, r);? ? ? ? ? ? ? ? g = std::min(255, g);? ? ? ? ? ? ? ? b = std::min(255, b);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? image.setPixel(x, y, Pixel(r, g, b));? ? ? ? ? ? }? ? ? ? }? ? ? ? ? ? ? ? // 添加暗角效果? ? ? ? addVignette(image);? ? }? ? private:? ? static void addVignette(Image& image) {? ? ? ? int centerX = image.getWidth() / 2;? ? ? ? int centerY = image.getHeight() / 2;? ? ? ? float maxDist = sqrt(centerX * centerX + centerY * centerY);? ? ? ? ? ? ? ? for (int y = 0; y < image.getHeight(); y++) {? ? ? ? ? ? for (int x = 0; x < image.getWidth(); x++) {? ? ? ? ? ? ? ? float dist = sqrt((x - centerX) * (x - centerX) +? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (y - centerY) * (y - centerY));? ? ? ? ? ? ? ? float factor = 1.0f - (dist / maxDist) * 0.7f;? ? ? ? ? ? ? ? factor = std::max(0.3f, factor);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Pixel p = image.getPixel(x, y);? ? ? ? ? ? ? ? p.r *= factor;? ? ? ? ? ? ? ? p.g *= factor;? ? ? ? ? ? ? ? p.b *= factor;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? image.setPixel(x, y, p);? ? ? ? ? ? }? ? ? ? }? ? }};

7.2 黑白濾鏡

<cpp>

class BlackWhiteFilter {public:? ? // 普通黑白? ? static void applyGrayscale(Image& image) {? ? ? ? for (int y = 0; y < image.getHeight(); y++) {? ? ? ? ? ? for (int x = 0; x < image.getWidth(); x++) {? ? ? ? ? ? ? ? Pixel p = image.getPixel(x, y);? ? ? ? ? ? ? ? int gray = 0.299 * p.r + 0.587 * p.g + 0.114 * p.b;? ? ? ? ? ? ? ? image.setPixel(x, y, Pixel(gray, gray, gray));? ? ? ? ? ? }? ? ? ? }? ? }? ? ? ? // 高對

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容