位图Alpha斜角算法?


14

我正在寻找一种创建算法,该算法使用Alpha作为凹凸贴图将斜角效果添加到位图。

我将如何去做这样的事情?我尝试了镜面照明,但只得到高光而不是阴影。

这是我正在谈论的效果(使用Photoshop制作): 在此处输入图片说明

所有这些都使用size: 30px(从位图轮廓到斜角的深度)angle 130,,来完成altitude 50

从左到右,从上到下:

  1. 凿子硬锥
  2. 凿子软锥
  3. 平滑斜角
  4. 凿子硬soften: 16px-斜角模糊?

我正在尝试创建每种效果,我将如何创建基本斜角?而我需要从那个斜角获得每个

Answers:


10

这可以通过距离变换的卷积来实现。

在蒙版的边缘上使用距离变换。然后对该距离变换进行阈值处理,以删除超出某个距离的值。我认为获取阴影的秘诀在于将距离转换结果与看起来像这样的内核进行卷积:

[ -1.0  -1.0  -1.0
  -1.0   0.0   0.0
  -1.0   0.0   1.0 ]

这应该使您朝正确的方向开始:

#include "opencv/cv.h"
#include "opencv/highgui.h"

using namespace cv;
using namespace std;

int main() {
    Mat mask, dist, bevel;
    mask = Mat::zeros(200, 400, CV_8U);
    rectangle(mask, Point(30,30), Point(180,180), Scalar(255), -1);
    circle(mask, Point(30,30), 50, Scalar(0), -1);
    circle(mask, Point(180,180), 50, Scalar(0), -1);
    circle(mask, Point(300,100), 75, Scalar(255), -1);
    imshow("1",mask);

在此处输入图片说明

    //find edges and invert image for distance transform
    Canny(mask, dist, 50, 150);
    dist = 255-dist;
    distanceTransform(dist, dist, CV_DIST_L2, CV_DIST_MASK_5);
    threshold(dist, dist, 20, 20, CV_THRESH_TRUNC);
    blur(dist, dist, Size(3,3));
    dist.convertTo(bevel, CV_8U);
    equalizeHist(bevel, bevel);
    imshow("2",bevel);

在此处输入图片说明

    //convolve with secret sauce
    float d[] = {-1,-2,-3,
                 -2, 0, 0,
                 -3, 0, 1 };
    Mat kernel(3, 3, CV_32F, d);
    kernel = kernel - mean(kernel)[0];
    filter2D(dist, dist, CV_32F, kernel);

    //normalize filtering result to [-1, 1]
    double maxVal;
    minMaxLoc(dist, NULL, &maxVal);
    dist = 128 * dist / maxVal;

    //convert and display result
    dist.convertTo(bevel, CV_8U, 1, 128);
    bevel = bevel.mul(mask)/255;
    imshow("3", bevel);

在此处输入图片说明

    waitKey(0);
}

那些看起来很棒!柔化的表面看起来像是模糊的,但是我该如何用它们制作“平滑的斜面”呢?
Shedokan,2011年

我相信“平滑斜角”会在卷积之前模糊距离蒙版,而“柔化”会在卷积之后模糊结果。
Matt M.

4

Photoshop的Bevel和Emboss可以正常工作:

1)在一个临时的8位单通道图像中计算距离变换

  • 凿子使用带有倒角度量标准的欧几里德距离变换(3x3、5x5或7x7,取决于大小)。如果需要,可以使用精确的欧几里德距离变换,我更喜欢Meijster的方法,因为它可以进行抗锯齿(“用于计算线性时间中距离变换的通用算法”,MEIJSTER)。

  • 平滑斜角使用倒角5-7-11距离变换,然后两次应用盒子模糊,以生成凹凸贴图。

2)将凹凸贴图应用于中间距离变换图像。布林的原始技术是合适的。

3)要进行软化,可以对表面法线进行卷积,也可以使用内核对其进行过滤。

4)使用凹凸贴图,将表面法线与全局光源组合以将照明强度计算为-1到1的值,其中负值是阴影,正值是高光,绝对值是光的强度资源。

5)计算两个8位单通道临时图像,一个来自高光强度,另一个来自阴影。从那里开始,使用颜色,混合模式和不透明度使用每个蒙版对图层进行着色很简单-一个蒙版用于高光,另一个蒙版用于阴影。

可在此处找到用于实现其中一些功能的Visual Basic源代码:

http://www.Planet-Source-Code.com/vb/scripts/ShowCode.asp?txtCodeId=51640&lngWId=1

请访问我的开源LayerEffects项目以了解更多信息:

https://github.com/vinniefalco/LayerEffects.git

我希望这可以帮助别人。


谢谢,我对您提到的高斯距离变换非常感兴趣,您知道可用的任何代码吗?我无法很好地阅读公式。:(
Shedokan

除了我已经发布的信息之外,我没有找到任何有关GDT的信息。
Vinnie Falco

“ 2)将凹凸贴图应用于距离变换图像”是什么意思?距离变换给出距离(每个像素1个数字),而凹凸贴图需要法线(每个像素2个数字)...您确定知道您在说什么吗?
伊万·库基尔

@IvanKuckir我应该更加清楚-可以通过将距离变换视为高度图并从相邻的垂直和水平值计算dx / dy来计算表面法线。这两个数字提供了凹凸贴图所需的法线。
温妮·佛尔科
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.