实现Photoshop缎面效果:如何处理XOR运算的交集问题?
问题
我想要复刻Photoshop中的缎面效果,该效果通过生成缎面纹理并应用类模糊效果来创建污渍质感。我认为实现步骤为:对输入图案进行双位移,执行XOR运算得到缎面图案,再应用高斯模糊并处理XOR运算的交集。
目前我已完成图案位移部分,代码如下:
apple = cv2.imread('apple.png') apple = cv2.cvtColor(apple, cv2.COLOR_BGR2GRAY) # User Inputs (Similar to Photoshop) angle = 41 # angle of the shift distance = 100 # distance of the shift angle = np.deg2rad(180-angle) tx, ty = (distance*np.cos(angle),distance*np.sin(angle)) # Shifting shift_matrix1 = np.array([[1,0,tx],[0,1,ty]], dtype=np.float32) shift_matrix2 = np.array([[1,0,-tx],[0,1,-ty]], dtype=np.float32) shift1 = cv2.warpAffine(apple, shift_matrix1, apple.shape) shift2 = cv2.warpAffine(apple,shift_matrix2, apple.shape) # XOR Operation xor_result = cv2.bitwise_not(cv2.bitwise_and(cv2.bitwise_xor(shift1, shift2), apple)) output = cv2.bitwise_and(xor_result, apple)
这部分能得到与Photoshop近似的效果。但在XOR运算前添加高斯模糊(代码如下)后,结果出现异常像素,与Photoshop的效果不符。
... shift1 = cv2.GaussianBlur(shift1, (101,101),0) shift2 = cv2.GaussianBlur(shift2, (101,101),0) # XOR Operation xor_result = ...
请问需要添加什么操作来处理这两个图形XOR运算的交集问题?
解决方案
问题核心是模糊后的图像不再是纯黑白二值状态——高斯模糊会生成灰度渐变的像素值,而OpenCV的位运算(XOR、AND等)是基于8位二进制逐位计算的,灰度中间值会导致异常像素,和Photoshop基于图层混合模式的逻辑完全不符。
要复刻Photoshop的缎面模糊效果,需要调整步骤,将二进制位运算替换为灰度级数值运算,具体操作如下:
- 先对原始图像做双位移,得到两个偏移图层
- 对两个偏移图层分别做高斯模糊
- 用灰度差值的绝对值模拟XOR的视觉效果(二值图中XOR代表两图不同区域,对应灰度图中差值大的区域)
- 将结果与原始图像做蒙版融合,保留原始图像的轮廓
修改后的完整代码:
import cv2 import numpy as np apple = cv2.imread('apple.png') apple = cv2.cvtColor(apple, cv2.COLOR_BGR2GRAY).astype(np.float32) / 255.0 # 归一化到0-1范围 # User Inputs (Similar to Photoshop) angle = 41 # angle of the shift distance = 100 # distance of the shift angle = np.deg2rad(180 - angle) tx, ty = (distance * np.cos(angle), distance * np.sin(angle)) # Shifting shift_matrix1 = np.array([[1, 0, tx], [0, 1, ty]], dtype=np.float32) shift_matrix2 = np.array([[1, 0, -tx], [0, 1, -ty]], dtype=np.float32) shift1 = cv2.warpAffine(apple, shift_matrix1, apple.shape[::-1]) shift2 = cv2.warpAffine(apple, shift_matrix2, apple.shape[::-1]) # 先模糊再处理,替换位运算为灰度级运算 shift1_blur = cv2.GaussianBlur(shift1, (101, 101), 0) shift2_blur = cv2.GaussianBlur(shift2, (101, 101), 0) # 用绝对值差值模拟XOR的视觉效果(二值XOR是不同区域,灰度图对应差值大的区域) xor_gray = np.abs(shift1_blur - shift2_blur) # 与原始图像融合,保留原始轮廓(对应原代码中的bitwise_and逻辑) output = xor_gray * apple # 转换回8位图像 output = (output * 255).astype(np.uint8) cv2.imwrite('satin_effect.png', output)
关键说明
- 将图像归一化到0-1的浮点范围,避免整数运算的精度损失
- 用
np.abs(shift1_blur - shift2_blur)替代二进制XOR,更贴合Photoshop中模糊后图层混合的灰度逻辑 - 最后与原始图像相乘,实现蒙版效果,保留原始图像的主体轮廓
内容的提问来源于stack exchange,提问作者SaulGoodMan
相关产品推荐
相关产品推荐

