Алгоритм скошування альфа-коси


14

Я шукаю створити алгоритм, який додає ефект скосу до растрової карти, використовуючи альфа як ударну карту.

Як би я пішов робити щось подібне? Я спробував дзеркальне освітлення, але отримую лише родзинку, а не відтінок.

Ось ефект, про який я говорю (зроблений за допомогою Photoshop): введіть тут опис зображення

Все це було зроблено з допомогою size: 30px(глибина скоса від контуру бітової карти), angle 130, altitude 50.

Зліва направо, зверху вниз:

  1. Зубило Твердий скос
  2. Зубило м'яке скошення
  3. Гладкий скос
  4. Зубило тверде з soften: 16px- розмита скоса?

Я намагаюся створити кожен із цих ефектів, як би я пішов про створення базового скосу? і що мені потрібно, щоб дістатись до кожного із цього скосу

Відповіді:


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);
}

Вони виглядають приголомшливо! Той, що розм’якшився, виглядає як розмиття, але як би я пішов робити з них «Гладкий скос»?
Шедокан

Я вважаю, що Smooth Bevel розмиває маску відстані перед згортанням, а Soften розмиває результат після згортання.
Метт М.

4

Photoshop's Bevel and Emboss працює передбачувано:

1) Обчислити перетворення відстані у тимчасовому 8-бітовому одноканальному зображенні

  • Долото використовує евклідову дистанційну трансформацію з метрикою фаски (3x3, 5x5 або 7x7 залежно від розміру). Якщо ви хочете, ви можете використовувати точне перетворення евклідової відстані, я віддаю перевагу такому від Meijster, оскільки його можна зробити антисеансинним ("Загальний алгоритм для обчислення перетворень на відстані в лінійний час", MEIJSTER).

  • Smooth Bevel використовує трансформацію відстані на Шамарі 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

Я сподіваюся, що це комусь допоможе.


Дякую, я дуже зацікавлений у згадуваній вами гауссовій дистанційній трансформації, чи знаєте ви про будь-який доступний код? Я не вмію добре читати формули. :(
Шедокан

Я нічого не знайшов про GDT, окрім інформації, яку я вже розмістив.
Vinnie Falco

Що ви маєте на увазі під "2) Застосувати відмінне відображення до зображення перетворення відстані"? Перетворення відстані дає відстані (1 число на кожен піксель), тоді як для Bump-картографування потрібні нормальні норми (2 числа на кожен піксель) ... Ви впевнені, що знаєте, про що говорите?
Іван Кукір

@IvanKuckir Я повинен був бути більш чітким - нормальність поверхні може бути обчислена, розглядаючи перетворення відстані як мапу висоти та обчислюючи dx / dy від сусідніх вертикальних та горизонтальних значень. Ці два числа забезпечують нормальну величину, необхідну для зіставлення ударів.
Вінні Фалько
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.