Photoshop中的自由锐化算法Photoshop中的自由锐化算法Smart Sharpen是一种用于图像锐化的技术旨在增强图像的细节同时减少噪点和不必要的伪影。其基本原理可以概述为以下几个方面图像的边缘增强锐化过程主要集中在图像的边缘部分。通过增强边缘的对比度使得图像看起来更加清晰。通常使用的是拉普拉斯算子或基于梯度的算法来检测边缘。高通滤波自由锐化常常利用高通滤波的原理去除图像中的低频部分即平坦区域仅保留高频信息即边缘和细节。通过增强高频信息图像更显得锐利。自适应强度调整自由锐化算法提供了对锐化强度和半径的自定义设置。用户可以根据具体图像的需求调整这些参数以获得最佳效果。这使得用户能够在不同类型的图像上灵活运用锐化技术。智能去噪自由锐化还提供了一些智能去噪的选项能够在锐化过程中识别和减少噪点避免在细节增强的同时增加图像的噪声。预览和反馈Photoshop的自由锐化功能允许用户实时预览效果使得用户可以在应用变化之前看到调整后的效果从而更好地控制最终输出的结果。总而言之自由锐化算法结合了边缘检测、频域处理和自适应调整等技术以最大限度地增强图像细节同时保持自然的外观。其灵活性和多功能性使其成为图像后期处理中非常重要的工具。Mat FreeSharp(Mat src, float sharpDegree 0.3) { int row src.rows; int col src.cols; int border 1; Mat dst(row, col, CV_8UC3); for (int i border; i row - border; i) { for (int j border; j col - border; j) { for (int k 0; k 3; k) { int sum 9 * src.atVec3b(i, j)[k] - src.atVec3b(i - 1, j - 1)[k] - src.atVec3b(i - 1, j)[k] - src.atVec3b(i - 1, j 1)[k] - src.atVec3b(i, j - 1)[k] - src.atVec3b(i, j 1)[k] - src.atVec3b(i 1, j - 1)[k] - src.atVec3b(i 1, j)[k] - src.atVec3b(i 1, j 1)[k]; sum sum * sharpDegree 0.5; if (sum 255) sum 255; else if (sum 0) sum 0; dst.atVec3b(i, j)[k] sum; } } } return dst; }图像转置算法图像转置也称为图像旋转或交换行列是一种常见的图像处理操作主要用于将图像的行和列进行交换。在 Photoshop 中转置操作可以通过特定的滤镜或图层操作进行实现。下面是图像转置的基本原理原理图像可以看作是一个二维数组其中每个元素表示像素的颜色值。对于一个宽度为W高度为H的图像转置操作的基本步骤如下创建一个新的数组生成一个新的二维数组宽度为H高度为W。数据交换遍历原始图像的每个像素将其位置(x, y)的像素值复制到新数组的位置(y, x)。填充新图像通过新数组生成转置后的图像。具体步骤假设原始图像像素数组为original[x][y]转置后的数组为transposed[y][x]转置的过程可以描述如下初始化一个新的空数组transposed[H][W]。对于每个像素执行以下操作transposed[y][x] original[x][y]根据转置后的数组生成最终图像。示例假设有一个 2x3 的图像2 行 3 列原始图像 1 2 3 4 5 6复制代码转置后的图像将变为 3x2转置图像 1 4 2 5 3 6复制代码注意事项边界处理需要小心处理图像边界以免出现数组越界。性能问题在处理大图像时转置操作可能会消耗较多内存和处理时间因此在实际应用中可能需要考虑优化方案。格式转换转置后的图像可能需要重新保存或者转换成特定格式以适应下游处理。通过理解上述原理可以在 Photoshop 及其他图像处理软件中更好地掌握图像转置操作。Mat Transposition(Mat src) { int row src.rows; int col src.cols; Mat dst(col, row, CV_8UC3); for (int i 0; i row; i){ for (int j 0; j col; j) { for (int k 0; k 3; k) { dst.atVec3b(j, i) src.atVec3b(i, j); } } } return dst; }图像缩放算法在Photoshop中图像缩放是通过多种算法来实现的这些算法会影响图像缩放后的质量和细节保留。以下是一些主要的图像缩放算法及其原理最近邻插值 (Nearest Neighbor Interpolation):原理这是最简单的插值方法。当缩放图像时它会选择离目标像素最近的源像素的颜色值。而不进行任何复杂计算。优点计算速度快适用于低质量需求。缺点图像在放大时会出现锯齿边缘细节保留差。双线性插值 (Bilinear Interpolation):原理除了考虑目标像素最近的四个邻近像素的颜色值外还会根据它们的距离进行加权平均从而得到新的像素值。优点比最近邻插值效果好图像较为平滑。缺点在大幅放大图像时仍可能出现模糊。双三次插值 (Bicubic Interpolation):原理考虑目标像素周围的16个像素根据其距离进行加权平均。此方法利用了更高级的数学模型来计算新像素值。优点比双线性插值能够更好地保留细节和纹理生成的图像更为平滑。缺点处理速度较慢计算复杂。Lanczos重采样 (Lanczos Resampling):原理基于带限重采样理论使用高斯函数作为内插核对更多邻近像素进行加权处理。通常使用8个或更多的像素来获得新的像素值。优点保留更多的细节和边缘效果图像质量高。缺点计算非常复杂处理速度较慢。Spline插值:原理使用分段多项式来平滑插值常用于高质量图像的缩放。优点具有平滑的特性能更好地处理图像的细节。缺点计算复杂可能消耗较多的时间。在Photoshop中图像缩放时可以选择不同的插值算法以满足不同的需求。通常在调整图像大小时最常用的高质量算法是双三次插值或Lanczos重采样具体选择可以根据用户的需求及图像特性来决定。Mat Resize(Mat src, float sx, float sy) { int row src.rows; int col src.cols; int channels src.channels(); int dst_row round(row * sx); int dst_col round(col * sy); if (channels 1) { Mat dst(dst_row, dst_col, CV_8UC1); for (int i 0; i dst_row; i) { for (int j 0; j dst_col; j) { int pre_i round(i / sy); int pre_j round(j / sx); if (pre_i row - 1) pre_i row - 1; if (pre_j col - 1) pre_j col - 1; dst.atuchar(i, j) src.atuchar(pre_i, pre_j); } } return dst; } else { Mat dst(dst_row, dst_col, CV_8UC3); for (int i 0; i dst_row; i) { for (int j 0; j dst_col; j) { int pre_i round(i / sy); int pre_j round(j / sx); if (pre_i row - 1) pre_i row - 1; if (pre_j col - 1) pre_j col - 1; dst.atVec3b(i, j)[0] src.atVec3b(pre_i, pre_j)[0]; dst.atVec3b(i, j)[1] src.atVec3b(pre_i, pre_j)[1]; dst.atVec3b(i, j)[2] src.atVec3b(pre_i, pre_j)[2]; } } return dst; } }最近邻插值(Nearest Neighbor Interpolation)最近邻插值通过找到目标像素在原图像中最近的像素值来赋值给目标像素。具体来说根据原图像和目标图像的尺寸计算缩放的比例然后根据缩放比例计算目标像素所依据的原像素并将该值赋给目标像素。最近邻插值的优点:算法简单计算量小速度快。不会产生新的像素值保持原始图像的灰度值。最近邻插值的缺点:容易产生锯齿现象图像质量较低。下面的代码展示了如何实现最近邻插值算法#include opencv2/highgui/highgui.hpp #include opencv2/imgproc/imgproc.hpp using namespace std; using namespace cv; //最近邻插值算法 void nearestNeighbor(cv::Mat src, cv::Mat dst, float sx, float sy) { // 由 scale 计算输出图像的尺寸四舍五入 int dst_cols round(src.cols * sx); int dst_rows round(src.rows * sy); dst cv::Mat(dst_rows,dst_cols,src.type()); for (int i 0; i dst.rows; i){ for (int j 0; j dst.cols; j){ if (src.channels() 1) { // 插值计算输出图像的像素点由原图像对应的最近的像素点得到四舍五入 int i_index round(i / sy); int j_index round(j / sx); if (i_index src.rows - 1) i_index src.rows - 1;//防止越界 if (j_index src.cols - 1) j_index src.cols - 1;//防止越界 dst.atuchar(i, j) src.atuchar(i_index, j_index); } else { // 插值计算输出图像的像素点由原图像对应的最近的像素点得到四舍五入 int i_index round(i / sy); int j_index round(j / sx); if (i_index src.rows - 1) i_index src.rows - 1;//防止越界 if (j_index src.cols - 1) j_index src.cols - 1;//防止越界 dst.atcv::Vec3b(i, j)[0] src.atcv::Vec3b(i_index, j_index)[0]; dst.atcv::Vec3b(i, j)[1] src.atcv::Vec3b(i_index, j_index)[1]; dst.atcv::Vec3b(i, j)[2] src.atcv::Vec3b(i_index, j_index)[2]; } } } } int main() { Mat src imread(.../grass.jpg); imshow(src, src); Mat dst; nearestNeighbor(src, dst,1.5, 1.5); imshow(dst, dst); waitKey(0); return 0; }typedef cv::Point3_uint8_t Pixel; //最近邻插值算法 void nearestNeighbor(cv::Mat src, cv::Mat dst, float sx, float sy) { // 由 scale 计算输出图像的尺寸四舍五入 int dst_cols round(src.cols * sx); int dst_rows round(src.rows * sy); dst cv::Mat(dst_rows,dst_cols,src.type()); dst.forEachPixel([](Pixel p, const int * position) - void { int row position[0]; int col position[1]; if (src.channels() 1) { int i_index round(row / sy); int j_index round(col / sx); dst.atuchar(row, col) src.atuchar(i_index, j_index); } else { int i_index round(row/ sy); int j_index round(col / sx); dst.atcv::Vec3b(row, col)[0] src.atcv::Vec3b(i_index, j_index)[0]; dst.atcv::Vec3b(row, col)[1] src.atcv::Vec3b(i_index, j_index)[1]; dst.atcv::Vec3b(row, col)[2] src.atcv::Vec3b(i_index, j_index)[2]; } }); }双线性插值是对 x 方向和 y 方向分别进行插值它根据原始图像中四个相邻像素的值来估计新位置处像素的值。它是一维线性插值的扩展 。此时一共执行了三次线性插值双线性插值只是对 x、y 方向进行插值而不是进行两次插值。双线性插值用于根据原始图像中的已知值来估计调整大小的图像中像素的强度或颜色值。 与最近邻插值相比这种方法可以产生更平滑的结果后者可能会导致可见的伪影或锯齿状边缘。下面的代码展示了如何实现双线性插值算法。#include opencv2/opencv.hpp using namespace cv; using namespace std; typedef cv::Point3_uint8_t Pixel; // 双线性插值算法 void bilinearInterpolation(Mat src, Mat dst, double sx, double sy) { int dst_rows static_castint(src.rows * sy); int dst_cols static_castint(src.cols * sx); dst Mat::zeros(cv::Size(dst_cols, dst_rows), src.type()); dst.forEachPixel([](Pixel p, const int * position) - void { int row position[0]; int col position[1]; // (col,row)为目标图像坐标 // (before_x,before_y)原图坐标 double before_x double(col 0.5) / sx - 0.5f; double before_y double(row 0.5) / sy - 0.5; // 原图像坐标四个相邻点 // 获得变换前最近的四个顶点,取整 int top_y static_castint(before_y); int bottom_y top_y 1; int left_x static_castint(before_x); int right_x left_x 1; //计算变换前坐标的小数部分 double u before_x - left_x; double v before_y - top_y; // 如果计算的原始图像的像素大于真实原始图像尺寸 if ((top_y src.rows - 1) (left_x src.cols - 1)) {//右下角 for (size_t k 0; k src.channels(); k) { dst.atVec3b(row, col)[k] (1\. - u) * (1\. - v) * src.atVec3b(top_y, left_x)[k]; } } else if (top_y src.rows - 1) { //最后一行 for (size_t k 0; k src.channels(); k) { dst.atVec3b(row, col)[k] (1\. - u) * (1\. - v) * src.atVec3b(top_y, left_x)[k] (1\. - v) * u * src.atVec3b(top_y, right_x)[k]; } } else if (left_x src.cols - 1) {//最后一列 for (size_t k 0; k src.channels(); k) { dst.atVec3b(row, col)[k] (1\. - u) * (1\. - v) * src.atVec3b(top_y, left_x)[k] (v) * (1\. - u) * src.atVec3b(bottom_y, left_x)[k]; } } else { for (size_t k 0; k src.channels(); k) { dst.atVec3b(row, col)[k] (1\. - u) * (1\. - v) * src.atVec3b(top_y, left_x)[k] (1\. - v) * (u) * src.atVec3b(top_y, right_x)[k] (v) * (1\. - u) * src.atVec3b(bottom_y, left_x)[k] (u) * (v) * src.atVec3b(bottom_y, right_x)[k]; } } }); } int main() { Mat src imread(.../grass.jpg); imshow(src, src); double sx 1.5; double sy 1.5; Mat dst; bilinearInterpolation(src,dst, sx, sy); imshow(dst, dst); waitKey(0); return 0; }图像素描算法图像素描算法的原理主要是通过处理图像的边缘和纹理来模拟手绘素描的效果。以下是一些基于Photoshop或其他图像处理软件中常见的素描效果的算法原理边缘检测素描效果的第一步通常是识别图像中的边缘。常用的边缘检测算法包括Sobel算子通过计算图像中亮度变化的梯度来检测边缘。Canny边缘检测一种多阶段算法具有较好的边缘检测效果包括噪声减少、强边缘和弱边缘的检测等。灰度化将彩色图像转换为灰度图像以简化后续处理。通常采用加权平均的方法对RGB通道进行处理。反转图像为了模拟铅笔素描效果可以对图像进行反转处理将明亮部分变为暗色暗色部分变为亮色。模糊处理使用高斯模糊或其他模糊技术来柔化图像中的细节使得最终结果更像手工素描的效果。混合模式将处理后的图像与原始图像结合通过不同的混合模式增强效果。例如使用“叠加”或“柔光”等模式可以增加图像的对比度和层次感。纹理添加可以添加一些纹理效果模拟纸张的质感使图像看起来更加逼真。亮度和对比度调整最后可以微调图像的亮度和对比度以使素描效果更加突出。在Photoshop中通常可以通过滤镜如“滤镜 艺术效果 草图”来实现这些步骤从而快速生成素描效果。不同的算法组合和参数调整能导致不同的素描风格用户可以根据自己的需求进行调整。Mat Sketch(Mat src) { int row src.rows; int col src.cols; Mat dst(row, col, CV_8UC1); Mat gray(row, col, CV_8UC1); cvtColor(src, dst, COLOR_BGR2GRAY); gray dst.clone(); for (int i 0; i row; i) { for (int j 0; j col; j) { dst.atuchar(i, j) 255 - dst.atuchar(i, j); } } GaussianBlur(dst, dst, Size(3, 3), 1.0); for (int i 0; i row; i) { for (int j 0; j col; j) { double b double(dst.atuchar(i, j)); double a double(gray.atuchar(i, j)); int temp (int)(a a*b / (256.0 - b)); if (temp 255) temp 255; dst.atuchar(i, j) temp; } } return dst; }色调分离算法色调分离Tonal Separation在Photoshop中通常用于调整图像的色调和对比度使得不同色调区域更加突出。这种算法的原理主要包括以下几个方面1.色彩空间转换通常将图像从RGB色彩空间转换到其他色彩空间如HSV、Lab等这样可以更方便地操作亮度、饱和度和色度。HSV色相、饱和度、明度允许更直观地调整色调和亮度而不影响色彩本身。2.色调分离对图像的亮度和色相通道进行分离。图像的不同亮度范围可以被独立处理。图像中的亮度信息可以被分为阴影、中间调和高光各自进行处理以增强细节对比度等。3. ** tonal mapping**应用“调色映射”Tonal Mapping技术可以使高对比度的图像在低动态范围的显示器上更好地呈现。可以根据目标视觉效果进行非线性调整以强调某些色调范围。4.曲线与级别调整通过调整曲线或级别来改变图像的对比度和亮度。根据需要拉伸或压缩某些色调区间。在阴影和高光部分应用不同的增益和Gamma值以增强细节。5.分层效果Photoshop支持图层技术可以在不同的图层上应用不同的色调调整不会影响原始图像。可以使用调整图层、图层蒙版等灵活控制每个部分的色调。6.算法实现使用图像处理算法如高斯模糊、边缘检测等来进一步精细化分离效果确保在强度、边缘等方面得到优化。应用实例局部调整可以利用选区工具或快速蒙版直观地选中需要处理的色调范围比如增强天空的蓝色。创意效果创建艺术效果时通过色调分离可以模仿胶卷摄影的特征增加胶卷颗粒感或色彩失真。通过这些技术Photoshop能够实现复杂的色调分离极大地提升图像的表现力和艺术感。Mat Posterize(Mat src, int Num) { int row src.rows; int col src.cols; int Step 255 / (Num - 1); vector int T; for (int i 1; i Num; i) { T.push_back((i - 1) * Step); } Mat dst(row, col, CV_8UC3); Step floor(255 / Num) 1; for (int i 0; i row; i) { for (int j 0; j col; j) { for (int k 0; k 3; k) { dst.atVec3b(i, j)[k] T[floor(src.atVec3b(i, j)[k] / Step)]; } } } return dst; }Num要大于2。更多PS代码请关注我上传的资源文件。https://download.csdn.net/download/m0_44975814/89896121
PS算法及c++代码(一)(可直接复制运行,代码在文末)
Photoshop中的自由锐化算法Photoshop中的自由锐化算法Smart Sharpen是一种用于图像锐化的技术旨在增强图像的细节同时减少噪点和不必要的伪影。其基本原理可以概述为以下几个方面图像的边缘增强锐化过程主要集中在图像的边缘部分。通过增强边缘的对比度使得图像看起来更加清晰。通常使用的是拉普拉斯算子或基于梯度的算法来检测边缘。高通滤波自由锐化常常利用高通滤波的原理去除图像中的低频部分即平坦区域仅保留高频信息即边缘和细节。通过增强高频信息图像更显得锐利。自适应强度调整自由锐化算法提供了对锐化强度和半径的自定义设置。用户可以根据具体图像的需求调整这些参数以获得最佳效果。这使得用户能够在不同类型的图像上灵活运用锐化技术。智能去噪自由锐化还提供了一些智能去噪的选项能够在锐化过程中识别和减少噪点避免在细节增强的同时增加图像的噪声。预览和反馈Photoshop的自由锐化功能允许用户实时预览效果使得用户可以在应用变化之前看到调整后的效果从而更好地控制最终输出的结果。总而言之自由锐化算法结合了边缘检测、频域处理和自适应调整等技术以最大限度地增强图像细节同时保持自然的外观。其灵活性和多功能性使其成为图像后期处理中非常重要的工具。Mat FreeSharp(Mat src, float sharpDegree 0.3) { int row src.rows; int col src.cols; int border 1; Mat dst(row, col, CV_8UC3); for (int i border; i row - border; i) { for (int j border; j col - border; j) { for (int k 0; k 3; k) { int sum 9 * src.atVec3b(i, j)[k] - src.atVec3b(i - 1, j - 1)[k] - src.atVec3b(i - 1, j)[k] - src.atVec3b(i - 1, j 1)[k] - src.atVec3b(i, j - 1)[k] - src.atVec3b(i, j 1)[k] - src.atVec3b(i 1, j - 1)[k] - src.atVec3b(i 1, j)[k] - src.atVec3b(i 1, j 1)[k]; sum sum * sharpDegree 0.5; if (sum 255) sum 255; else if (sum 0) sum 0; dst.atVec3b(i, j)[k] sum; } } } return dst; }图像转置算法图像转置也称为图像旋转或交换行列是一种常见的图像处理操作主要用于将图像的行和列进行交换。在 Photoshop 中转置操作可以通过特定的滤镜或图层操作进行实现。下面是图像转置的基本原理原理图像可以看作是一个二维数组其中每个元素表示像素的颜色值。对于一个宽度为W高度为H的图像转置操作的基本步骤如下创建一个新的数组生成一个新的二维数组宽度为H高度为W。数据交换遍历原始图像的每个像素将其位置(x, y)的像素值复制到新数组的位置(y, x)。填充新图像通过新数组生成转置后的图像。具体步骤假设原始图像像素数组为original[x][y]转置后的数组为transposed[y][x]转置的过程可以描述如下初始化一个新的空数组transposed[H][W]。对于每个像素执行以下操作transposed[y][x] original[x][y]根据转置后的数组生成最终图像。示例假设有一个 2x3 的图像2 行 3 列原始图像 1 2 3 4 5 6复制代码转置后的图像将变为 3x2转置图像 1 4 2 5 3 6复制代码注意事项边界处理需要小心处理图像边界以免出现数组越界。性能问题在处理大图像时转置操作可能会消耗较多内存和处理时间因此在实际应用中可能需要考虑优化方案。格式转换转置后的图像可能需要重新保存或者转换成特定格式以适应下游处理。通过理解上述原理可以在 Photoshop 及其他图像处理软件中更好地掌握图像转置操作。Mat Transposition(Mat src) { int row src.rows; int col src.cols; Mat dst(col, row, CV_8UC3); for (int i 0; i row; i){ for (int j 0; j col; j) { for (int k 0; k 3; k) { dst.atVec3b(j, i) src.atVec3b(i, j); } } } return dst; }图像缩放算法在Photoshop中图像缩放是通过多种算法来实现的这些算法会影响图像缩放后的质量和细节保留。以下是一些主要的图像缩放算法及其原理最近邻插值 (Nearest Neighbor Interpolation):原理这是最简单的插值方法。当缩放图像时它会选择离目标像素最近的源像素的颜色值。而不进行任何复杂计算。优点计算速度快适用于低质量需求。缺点图像在放大时会出现锯齿边缘细节保留差。双线性插值 (Bilinear Interpolation):原理除了考虑目标像素最近的四个邻近像素的颜色值外还会根据它们的距离进行加权平均从而得到新的像素值。优点比最近邻插值效果好图像较为平滑。缺点在大幅放大图像时仍可能出现模糊。双三次插值 (Bicubic Interpolation):原理考虑目标像素周围的16个像素根据其距离进行加权平均。此方法利用了更高级的数学模型来计算新像素值。优点比双线性插值能够更好地保留细节和纹理生成的图像更为平滑。缺点处理速度较慢计算复杂。Lanczos重采样 (Lanczos Resampling):原理基于带限重采样理论使用高斯函数作为内插核对更多邻近像素进行加权处理。通常使用8个或更多的像素来获得新的像素值。优点保留更多的细节和边缘效果图像质量高。缺点计算非常复杂处理速度较慢。Spline插值:原理使用分段多项式来平滑插值常用于高质量图像的缩放。优点具有平滑的特性能更好地处理图像的细节。缺点计算复杂可能消耗较多的时间。在Photoshop中图像缩放时可以选择不同的插值算法以满足不同的需求。通常在调整图像大小时最常用的高质量算法是双三次插值或Lanczos重采样具体选择可以根据用户的需求及图像特性来决定。Mat Resize(Mat src, float sx, float sy) { int row src.rows; int col src.cols; int channels src.channels(); int dst_row round(row * sx); int dst_col round(col * sy); if (channels 1) { Mat dst(dst_row, dst_col, CV_8UC1); for (int i 0; i dst_row; i) { for (int j 0; j dst_col; j) { int pre_i round(i / sy); int pre_j round(j / sx); if (pre_i row - 1) pre_i row - 1; if (pre_j col - 1) pre_j col - 1; dst.atuchar(i, j) src.atuchar(pre_i, pre_j); } } return dst; } else { Mat dst(dst_row, dst_col, CV_8UC3); for (int i 0; i dst_row; i) { for (int j 0; j dst_col; j) { int pre_i round(i / sy); int pre_j round(j / sx); if (pre_i row - 1) pre_i row - 1; if (pre_j col - 1) pre_j col - 1; dst.atVec3b(i, j)[0] src.atVec3b(pre_i, pre_j)[0]; dst.atVec3b(i, j)[1] src.atVec3b(pre_i, pre_j)[1]; dst.atVec3b(i, j)[2] src.atVec3b(pre_i, pre_j)[2]; } } return dst; } }最近邻插值(Nearest Neighbor Interpolation)最近邻插值通过找到目标像素在原图像中最近的像素值来赋值给目标像素。具体来说根据原图像和目标图像的尺寸计算缩放的比例然后根据缩放比例计算目标像素所依据的原像素并将该值赋给目标像素。最近邻插值的优点:算法简单计算量小速度快。不会产生新的像素值保持原始图像的灰度值。最近邻插值的缺点:容易产生锯齿现象图像质量较低。下面的代码展示了如何实现最近邻插值算法#include opencv2/highgui/highgui.hpp #include opencv2/imgproc/imgproc.hpp using namespace std; using namespace cv; //最近邻插值算法 void nearestNeighbor(cv::Mat src, cv::Mat dst, float sx, float sy) { // 由 scale 计算输出图像的尺寸四舍五入 int dst_cols round(src.cols * sx); int dst_rows round(src.rows * sy); dst cv::Mat(dst_rows,dst_cols,src.type()); for (int i 0; i dst.rows; i){ for (int j 0; j dst.cols; j){ if (src.channels() 1) { // 插值计算输出图像的像素点由原图像对应的最近的像素点得到四舍五入 int i_index round(i / sy); int j_index round(j / sx); if (i_index src.rows - 1) i_index src.rows - 1;//防止越界 if (j_index src.cols - 1) j_index src.cols - 1;//防止越界 dst.atuchar(i, j) src.atuchar(i_index, j_index); } else { // 插值计算输出图像的像素点由原图像对应的最近的像素点得到四舍五入 int i_index round(i / sy); int j_index round(j / sx); if (i_index src.rows - 1) i_index src.rows - 1;//防止越界 if (j_index src.cols - 1) j_index src.cols - 1;//防止越界 dst.atcv::Vec3b(i, j)[0] src.atcv::Vec3b(i_index, j_index)[0]; dst.atcv::Vec3b(i, j)[1] src.atcv::Vec3b(i_index, j_index)[1]; dst.atcv::Vec3b(i, j)[2] src.atcv::Vec3b(i_index, j_index)[2]; } } } } int main() { Mat src imread(.../grass.jpg); imshow(src, src); Mat dst; nearestNeighbor(src, dst,1.5, 1.5); imshow(dst, dst); waitKey(0); return 0; }typedef cv::Point3_uint8_t Pixel; //最近邻插值算法 void nearestNeighbor(cv::Mat src, cv::Mat dst, float sx, float sy) { // 由 scale 计算输出图像的尺寸四舍五入 int dst_cols round(src.cols * sx); int dst_rows round(src.rows * sy); dst cv::Mat(dst_rows,dst_cols,src.type()); dst.forEachPixel([](Pixel p, const int * position) - void { int row position[0]; int col position[1]; if (src.channels() 1) { int i_index round(row / sy); int j_index round(col / sx); dst.atuchar(row, col) src.atuchar(i_index, j_index); } else { int i_index round(row/ sy); int j_index round(col / sx); dst.atcv::Vec3b(row, col)[0] src.atcv::Vec3b(i_index, j_index)[0]; dst.atcv::Vec3b(row, col)[1] src.atcv::Vec3b(i_index, j_index)[1]; dst.atcv::Vec3b(row, col)[2] src.atcv::Vec3b(i_index, j_index)[2]; } }); }双线性插值是对 x 方向和 y 方向分别进行插值它根据原始图像中四个相邻像素的值来估计新位置处像素的值。它是一维线性插值的扩展 。此时一共执行了三次线性插值双线性插值只是对 x、y 方向进行插值而不是进行两次插值。双线性插值用于根据原始图像中的已知值来估计调整大小的图像中像素的强度或颜色值。 与最近邻插值相比这种方法可以产生更平滑的结果后者可能会导致可见的伪影或锯齿状边缘。下面的代码展示了如何实现双线性插值算法。#include opencv2/opencv.hpp using namespace cv; using namespace std; typedef cv::Point3_uint8_t Pixel; // 双线性插值算法 void bilinearInterpolation(Mat src, Mat dst, double sx, double sy) { int dst_rows static_castint(src.rows * sy); int dst_cols static_castint(src.cols * sx); dst Mat::zeros(cv::Size(dst_cols, dst_rows), src.type()); dst.forEachPixel([](Pixel p, const int * position) - void { int row position[0]; int col position[1]; // (col,row)为目标图像坐标 // (before_x,before_y)原图坐标 double before_x double(col 0.5) / sx - 0.5f; double before_y double(row 0.5) / sy - 0.5; // 原图像坐标四个相邻点 // 获得变换前最近的四个顶点,取整 int top_y static_castint(before_y); int bottom_y top_y 1; int left_x static_castint(before_x); int right_x left_x 1; //计算变换前坐标的小数部分 double u before_x - left_x; double v before_y - top_y; // 如果计算的原始图像的像素大于真实原始图像尺寸 if ((top_y src.rows - 1) (left_x src.cols - 1)) {//右下角 for (size_t k 0; k src.channels(); k) { dst.atVec3b(row, col)[k] (1\. - u) * (1\. - v) * src.atVec3b(top_y, left_x)[k]; } } else if (top_y src.rows - 1) { //最后一行 for (size_t k 0; k src.channels(); k) { dst.atVec3b(row, col)[k] (1\. - u) * (1\. - v) * src.atVec3b(top_y, left_x)[k] (1\. - v) * u * src.atVec3b(top_y, right_x)[k]; } } else if (left_x src.cols - 1) {//最后一列 for (size_t k 0; k src.channels(); k) { dst.atVec3b(row, col)[k] (1\. - u) * (1\. - v) * src.atVec3b(top_y, left_x)[k] (v) * (1\. - u) * src.atVec3b(bottom_y, left_x)[k]; } } else { for (size_t k 0; k src.channels(); k) { dst.atVec3b(row, col)[k] (1\. - u) * (1\. - v) * src.atVec3b(top_y, left_x)[k] (1\. - v) * (u) * src.atVec3b(top_y, right_x)[k] (v) * (1\. - u) * src.atVec3b(bottom_y, left_x)[k] (u) * (v) * src.atVec3b(bottom_y, right_x)[k]; } } }); } int main() { Mat src imread(.../grass.jpg); imshow(src, src); double sx 1.5; double sy 1.5; Mat dst; bilinearInterpolation(src,dst, sx, sy); imshow(dst, dst); waitKey(0); return 0; }图像素描算法图像素描算法的原理主要是通过处理图像的边缘和纹理来模拟手绘素描的效果。以下是一些基于Photoshop或其他图像处理软件中常见的素描效果的算法原理边缘检测素描效果的第一步通常是识别图像中的边缘。常用的边缘检测算法包括Sobel算子通过计算图像中亮度变化的梯度来检测边缘。Canny边缘检测一种多阶段算法具有较好的边缘检测效果包括噪声减少、强边缘和弱边缘的检测等。灰度化将彩色图像转换为灰度图像以简化后续处理。通常采用加权平均的方法对RGB通道进行处理。反转图像为了模拟铅笔素描效果可以对图像进行反转处理将明亮部分变为暗色暗色部分变为亮色。模糊处理使用高斯模糊或其他模糊技术来柔化图像中的细节使得最终结果更像手工素描的效果。混合模式将处理后的图像与原始图像结合通过不同的混合模式增强效果。例如使用“叠加”或“柔光”等模式可以增加图像的对比度和层次感。纹理添加可以添加一些纹理效果模拟纸张的质感使图像看起来更加逼真。亮度和对比度调整最后可以微调图像的亮度和对比度以使素描效果更加突出。在Photoshop中通常可以通过滤镜如“滤镜 艺术效果 草图”来实现这些步骤从而快速生成素描效果。不同的算法组合和参数调整能导致不同的素描风格用户可以根据自己的需求进行调整。Mat Sketch(Mat src) { int row src.rows; int col src.cols; Mat dst(row, col, CV_8UC1); Mat gray(row, col, CV_8UC1); cvtColor(src, dst, COLOR_BGR2GRAY); gray dst.clone(); for (int i 0; i row; i) { for (int j 0; j col; j) { dst.atuchar(i, j) 255 - dst.atuchar(i, j); } } GaussianBlur(dst, dst, Size(3, 3), 1.0); for (int i 0; i row; i) { for (int j 0; j col; j) { double b double(dst.atuchar(i, j)); double a double(gray.atuchar(i, j)); int temp (int)(a a*b / (256.0 - b)); if (temp 255) temp 255; dst.atuchar(i, j) temp; } } return dst; }色调分离算法色调分离Tonal Separation在Photoshop中通常用于调整图像的色调和对比度使得不同色调区域更加突出。这种算法的原理主要包括以下几个方面1.色彩空间转换通常将图像从RGB色彩空间转换到其他色彩空间如HSV、Lab等这样可以更方便地操作亮度、饱和度和色度。HSV色相、饱和度、明度允许更直观地调整色调和亮度而不影响色彩本身。2.色调分离对图像的亮度和色相通道进行分离。图像的不同亮度范围可以被独立处理。图像中的亮度信息可以被分为阴影、中间调和高光各自进行处理以增强细节对比度等。3. ** tonal mapping**应用“调色映射”Tonal Mapping技术可以使高对比度的图像在低动态范围的显示器上更好地呈现。可以根据目标视觉效果进行非线性调整以强调某些色调范围。4.曲线与级别调整通过调整曲线或级别来改变图像的对比度和亮度。根据需要拉伸或压缩某些色调区间。在阴影和高光部分应用不同的增益和Gamma值以增强细节。5.分层效果Photoshop支持图层技术可以在不同的图层上应用不同的色调调整不会影响原始图像。可以使用调整图层、图层蒙版等灵活控制每个部分的色调。6.算法实现使用图像处理算法如高斯模糊、边缘检测等来进一步精细化分离效果确保在强度、边缘等方面得到优化。应用实例局部调整可以利用选区工具或快速蒙版直观地选中需要处理的色调范围比如增强天空的蓝色。创意效果创建艺术效果时通过色调分离可以模仿胶卷摄影的特征增加胶卷颗粒感或色彩失真。通过这些技术Photoshop能够实现复杂的色调分离极大地提升图像的表现力和艺术感。Mat Posterize(Mat src, int Num) { int row src.rows; int col src.cols; int Step 255 / (Num - 1); vector int T; for (int i 1; i Num; i) { T.push_back((i - 1) * Step); } Mat dst(row, col, CV_8UC3); Step floor(255 / Num) 1; for (int i 0; i row; i) { for (int j 0; j col; j) { for (int k 0; k 3; k) { dst.atVec3b(i, j)[k] T[floor(src.atVec3b(i, j)[k] / Step)]; } } } return dst; }Num要大于2。更多PS代码请关注我上传的资源文件。https://download.csdn.net/download/m0_44975814/89896121