I am trying to make stamped metal effect into an image, so I go with applying bevel effect like in photoshop and I came across this question. This image for reference about what am I trying to achieve.
import cv2
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import cm
from PIL import Image
import scipy
def nothing(x):
pass
if __name__ == '__main__':
mask = np.zeros((200,400,1), np.uint8)
mask = cv2.rectangle(mask, (30,30), (180,180), 255, -1)
mask = cv2.circle(mask, (30,30), 50, 0, -1)
mask = cv2.circle(mask, (180,180), 50, 0, -1)
mask = cv2.circle(mask, (300,100), 75, 255, -1)
mask = cv2.circle(mask, (300,100), 25, 0, -1)
mask = cv2.rectangle(mask, (313,88), (338,110), 0, -1)
cv2.namedWindow('Bevel')
while(True):
light_angle = 0
depth = 7
alfa = 1.0
shift = 128
kernel_dist = np.ones((3,3), np.uint8)
dist = cv2.morphologyEx(mask, cv2.MORPH_GRADIENT, kernel_dist)
#dist = cv2.Canny(mask, 50,150)
dist = 255-dist
dist = cv2.distanceTransform(dist, cv2.DIST_L2, cv2.DIST_MASK_5)
_, dist = cv2.threshold(dist, depth, depth, cv2.THRESH_TRUNC)
dist = cv2.blur(dist, (3,3))
#bevel= np.array(dist, dtype=np.uint8) # not used, only to show stuff
#bevel= cv2.equalizeHist(bevel)
d = np.array([[-1,-2,-3],
[-2, 0, 0],
[-3, 0, 1]], dtype=np.float32)
d = scipy.ndimage.rotate(d,light_angle)
kernel = d - np.mean(d)
dist2 = cv2.filter2D(dist, cv2.CV_32F, kernel)
maxval = cv2.minMaxLoc(dist2)
dist2 = 128*dist2/maxval[1]
bevel2 = dist2
bevel2 = shift - bevel2 * alfa
bevel2 = np.multiply(bevel2.reshape(mask.shape), mask)/255
bg = np.zeros((200,400,3), np.float32)
bg = cv2.rectangle(bg, (30,30), (180,180), (150,150,0), -1)
bg = cv2.circle(bg, (30,30), 50, (0,0,0), -1)
bg = cv2.circle(bg, (180,180), 50, (0,0,0), -1)
bg = cv2.circle(bg, (300,100), 75, (0,200,0), -1)
bg = cv2.circle(bg, (300,100), 25, (0,0,0), -1)
bg = cv2.rectangle(bg, (313,88), (338,110), (0,0,0), -1)
bg_hsv = cv2.cvtColor(bg, cv2.COLOR_BGR2HSV)
h,s,v = cv2.split(bg_hsv)
v_blend = cv2.add(v,bevel2) #here merging bevel map and image via V channel
bg_hsv_new = cv2.merge([h,s,v_blend])
cv2.imshow('Bevel', cv2.cvtColor(bg_hsv_new, cv2.COLOR_HSV2BGR).astype(np.uint8))
if cv2.waitKey(10) & 0xFF == ord('q'):
break
The question is :
-
Is matrix/method that used on referenced question has an actual name? I couldn’t find any source that explain how said matrix/method work and how to tune it (such as strength of light, approach angle etc.)
-
Is my implementation of merging bevel map and actual image correct? The result become cool looking reflective metal effect, but that achieved after reducing parameter shift into 0 (where on referenced question used constant 128). If not, how to correctly use bevel map that produced?
Result :
Shift = 128
Shift = 0