当前位置: 首页 > article >正文

Photoshop图像算法(十)(代码在每个原理后面)

八方向浮雕算法

在 Photoshop 中,八方向浮雕效果(Emboss)主要是通过对图像进行高度图的处理,以模拟三维效果。其基本原理和算法可以归纳为以下几个步骤:

原理

  1. 高度图生成:将图像的亮度信息转化为高度。通常,亮部会被视为“高”,而暗部会被视为“低”。

  2. 法线计算:计算每个像素点的法线向量。通过对相邻像素的高度差进行比较,来确定表面在x和y方向的斜率。

  3. 光照模拟:根据法线向量和指定的光照方向计算每个像素的光照强度,以产生阴影和高光效果。

  4. 最终效果合成:将得到的光照信息与原始图像结合,形成浮雕效果。

算法步骤

  1. 灰度化:将输入图像转换为灰度图像,以便于进行高度处理。

  2. 获取邻域像素值:对每个像素,获取其周围邻域(通常是3x3或5x5)像素的值。

  3. 计算法线

    • 使用如下公式计算x和y方向的梯度(假设以 (i, j) 为中心像素):
      G_x = I(i+1, j) - I(i-1, j)
      G_y = I(i, j+1) - I(i, j-1)
  4. 计算浮雕效果

    • 使用以下公式来生成浮雕效果:
      E(i, j) = \text{sign}(G_x) \cdot \sqrt{|G_x|} + \text{sign}(G_y) \cdot \sqrt{|G_y|}
    • 其中,(\text{sign}(x)) 返回 x 的符号(正为 1,负为 -1,零为 0)。
  5. 应用光照模型

    • 假设光源方向为 (Lx, Ly, Lz),则每个像素的亮度可以由法线 (Nx, Ny, Nz) 与光源方向的点积来决定:
      I(i, j) = \max(0, N \cdot L)
  6. 对像素值进行归一化:将浮雕效果的值限制在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


http://www.kler.cn/a/371486.html

相关文章:

  • 关于我的数据结构与算法——初阶第二篇(排序)
  • C++之多态的深度剖析
  • 嵌入式学习-网络-Day03
  • Java应用程序的测试覆盖率之设计与实现(四)-- jacoco-maven-plugin
  • django celery 定时任务 Crontab 计划格式
  • UI设计软件全景:13款工具助力创意实现
  • 匹配销售策略的CRM系统挑选指南
  • 基于uniapp微信小程序的旅游系统
  • conda迁移虚拟环境路径
  • Halcon 颜色处理
  • 预览 PDF 文档
  • android 手机姿态(2)
  • scenedetect视频场景变换侦测与分割
  • Me 攒的GPT修改论文提示词
  • Unity GameFramework Star Force 拆解(一)—— 启动流程
  • 机器学习与神经网络:诺贝尔物理学奖的新方向
  • Gradle 配置后续一致更新
  • redis的三种客户端
  • SpringMVC学习(2)
  • Mac开发环境配置- Shell/Homebrew/ruby
  • ele-table表格列表内,双击编辑部分信息(el-table组件同理)
  • C# OpenCvSharp DNN UNet 推理
  • 华为手机系统应用瘦身
  • 了解桌面机床用于学校教学培训应用-桌面级CNC机床
  • Debug日程工作经验总结日程常用
  • 五指cms安装