Photoshop图像算法(十)(代码在每个原理后面)
八方向浮雕算法
在 Photoshop 中,八方向浮雕效果(Emboss)主要是通过对图像进行高度图的处理,以模拟三维效果。其基本原理和算法可以归纳为以下几个步骤:
原理
-
高度图生成:将图像的亮度信息转化为高度。通常,亮部会被视为“高”,而暗部会被视为“低”。
-
法线计算:计算每个像素点的法线向量。通过对相邻像素的高度差进行比较,来确定表面在x和y方向的斜率。
-
光照模拟:根据法线向量和指定的光照方向计算每个像素的光照强度,以产生阴影和高光效果。
-
最终效果合成:将得到的光照信息与原始图像结合,形成浮雕效果。
算法步骤
-
灰度化:将输入图像转换为灰度图像,以便于进行高度处理。
-
获取邻域像素值:对每个像素,获取其周围邻域(通常是3x3或5x5)像素的值。
-
计算法线:
- 使用如下公式计算x和y方向的梯度(假设以 (i, j) 为中心像素):
- 使用如下公式计算x和y方向的梯度(假设以 (i, j) 为中心像素):
-
计算浮雕效果:
- 使用以下公式来生成浮雕效果:
- 其中,(\text{sign}(x)) 返回 x 的符号(正为 1,负为 -1,零为 0)。
- 使用以下公式来生成浮雕效果:
-
应用光照模型:
- 假设光源方向为 (Lx, Ly, Lz),则每个像素的亮度可以由法线 (Nx, Ny, Nz) 与光源方向的点积来决定:
- 假设光源方向为 (Lx, Ly, Lz),则每个像素的亮度可以由法线 (Nx, Ny, Nz) 与光源方向的点积来决定:
-
对像素值进行归一化:将浮雕效果的值限制在0到255之间,使其符合图像的像素值范围。
注意事项
- 光源方向的选择会影响突出的效果。
- 在实际应用过程中,可能会结合其他图像处理技术,如模糊和锐化,以增强浮雕效果。
- 调整参数(如光照强度、浮雕深度等)可以产生不同的视觉效果。
这些步骤和公式概述了八方向浮雕效果的基本实现方法,可以在 Photoshop 或其他图像处理软件中进行类似的操作。
//8方向浮雕
enum DIR
{
N,
NE,
E,
SE,
S,
SW,
W,
NW
};
Mat DiamondEmboss(Mat src, DIR dir = SE, int offset = 127) {
int row = src.rows;
int col = src.cols;
int ioffset = 0;
int joffset = 0;
switch (dir)
{
case N:
ioffset = -1;
joffset = 0;
break;
case NE:
ioffset = -1;
joffset = 1;
break;
case E:
ioffset = 0;
joffset = 1;
break;
case SE:
ioffset = 1;
joffset = 1;
break;
case S:
ioffset = 1;
joffset = -1;
break;
case SW:
ioffset = 0;
joffset = -1;
break;
case W:
ioffset = 0;
joffset = -1;
break;
case NW:
ioffset = 1;
joffset = 1;
break;
default:
break;
}
Mat dst(row, col, CV_8UC3);
int border = 1;
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 = src.at<Vec3b>(i, j)[k] - src.at<Vec3b>(i - ioffset, j - joffset)[k] + offset;
if (sum < 0) sum = -sum;
if (sum < 64) sum = 64;
if (sum > 255) sum = 255;
dst.at<Vec3b>(i, j)[k] = sum;
}
}
}
return dst;
}
其他色彩特效
Mat ColorTrans(Mat src, int op) {
//op=1 呈现碧绿效果,就是要使色彩呈暗绿色,给人诡异的感觉
int row = src.rows;
int col = src.cols;
Mat dst(row, col, CV_8UC3);
if (op == 1) {
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
int b = src.at<Vec3b>(i, j)[0];
int g = src.at<Vec3b>(i, j)[1];
int r = src.at<Vec3b>(i, j)[2];
int R = (g - b) * (g - b) / 128;
int G = (r - b) * (r - b) / 128;
int B = (r - g) * (r - g) / 128;
if (R > 255) R = 255;
if (R < 0) R = 0;
if (G > 255) G = 255;
if (G < 0) G = 0;
if (B > 255) B = 255;
if (B < 0) B = 0;
dst.at<Vec3b>(i, j)[0] = B;
dst.at<Vec3b>(i, j)[1] = G;
dst.at<Vec3b>(i, j)[2] = R;
}
}
}
else if (op == 2) {
//op=2 棕褐色效果就是要实现那种图像模糊、略带发黄的老照片的感觉,别具风情
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
int b = src.at<Vec3b>(i, j)[0];
int g = src.at<Vec3b>(i, j)[1];
int r = src.at<Vec3b>(i, j)[2];
int R = 0.393 * r + 0.769 * g + 0.189 * b;
int G = 0.349 * r + 0.686 * g + 0.168 * b;
int B = 0.272 * r + 0.534 * g + 0.131 * b;
if (R > 255) R = 255;
if (R < 0) R = 0;
if (G > 255) G = 255;
if (G < 0) G = 0;
if (B > 255) B = 255;
if (B < 0) B = 0;
dst.at<Vec3b>(i, j)[0] = B;
dst.at<Vec3b>(i, j)[1] = G;
dst.at<Vec3b>(i, j)[2] = R;
}
}
}
else if (op == 3) {
//op=3 冰冻效果就是使图像呈现一种晶莹的淡蓝色
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
int b = src.at<Vec3b>(i, j)[0];
int g = src.at<Vec3b>(i, j)[1];
int r = src.at<Vec3b>(i, j)[2];
int R = abs(r - g - b) * 3 / 2;
int G = abs(g - b - r) * 3 / 2;
int B = abs(b - r - g) * 3 / 2;
if (R > 255) R = 255;
if (R < 0) R = 0;
if (G > 255) G = 255;
if (G < 0) G = 0;
if (B > 255) B = 255;
if (B < 0) B = 0;
dst.at<Vec3b>(i, j)[0] = B;
dst.at<Vec3b>(i, j)[1] = G;
dst.at<Vec3b>(i, j)[2] = R;
}
}
}
else if (op == 4) {
//op=4 熔铸效果类似打铁的场景
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
int b = src.at<Vec3b>(i, j)[0];
int g = src.at<Vec3b>(i, j)[1];
int r = src.at<Vec3b>(i, j)[2];
int R = r * 128 / (g + b + 1);
int G = g * 128 / (b + r + 1);
int B = b * 128 / (r + g + 1);
if (R > 255) R = 255;
if (R < 0) R = 0;
if (G > 255) G = 255;
if (G < 0) G = 0;
if (B > 255) B = 255;
if (B < 0) B = 0;
dst.at<Vec3b>(i, j)[0] = B;
dst.at<Vec3b>(i, j)[1] = G;
dst.at<Vec3b>(i, j)[2] = R;
}
}
}
else if (op == 5) {
//op=5 暗调效果是通过降低色彩的各个分量,使整幅图像变得深谙
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
int b = src.at<Vec3b>(i, j)[0];
int g = src.at<Vec3b>(i, j)[1];
int r = src.at<Vec3b>(i, j)[2];
int R = r * r / 255;
int G = g * g / 255;
int B = b * b / 255;
/*if (R > 255) R = 255;
if (R < 0) R = 0;
if (G > 255) G = 255;
if (G < 0) G = 0;
if (B > 255) B = 255;
if (B < 0) B = 0;*/
dst.at<Vec3b>(i, j)[0] = B;
dst.at<Vec3b>(i, j)[1] = G;
dst.at<Vec3b>(i, j)[2] = R;
}
}
}
else if (op == 6) {
//op=6 对调效果通过对彩色分量进行轮换的方式重新组合得到新的色彩
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
int b = src.at<Vec3b>(i, j)[0];
int g = src.at<Vec3b>(i, j)[1];
int r = src.at<Vec3b>(i, j)[2];
int R = g * b / 255;
int G = b * r / 255;
int B = r * g / 255;
/*if (R > 255) R = 255;
if (R < 0) R = 0;
if (G > 255) G = 255;
if (G < 0) G = 0;
if (B > 255) B = 255;
if (B < 0) B = 0;*/
dst.at<Vec3b>(i, j)[0] = B;
dst.at<Vec3b>(i, j)[1] = G;
dst.at<Vec3b>(i, j)[2] = R;
}
}
}
return dst;
}
更多PS代码请关注我上传的资源文件。
https://download.csdn.net/download/m0_44975814/89896121