Alpha-Abschrägungsalgorithmus für Bitmaps?


14

Ich möchte einen Algorithmus erstellen, der einer Bitmap einen Abschrägungseffekt hinzufügt, indem er Alpha als Reliefkarte verwendet.

Wie würde ich so etwas machen? Ich habe Spiegelbeleuchtung ausprobiert, aber ich bekomme nur das Highlight und nicht den Schatten.

Hier ist der Effekt, über den ich spreche (mit Photoshop erstellt): Bildbeschreibung hier eingeben

Alle diese wurden durchgeführt unter Verwendung size: 30px(die Tiefe der Abschrägung von der Kontur des Bitmaps) angle 130, altitude 50.

Von links nach rechts, von oben nach unten:

  1. Meißel Harte Abschrägung
  2. Meißel Soft Bevel
  3. Glatte Abschrägung
  4. Meißel hart mit soften: 16px- eine unscharfe Abschrägung?

Ich versuche, jeden dieser Effekte zu erstellen. Wie würde ich vorgehen, um die Grundfase zu erstellen? und was brauche ich, um von dieser Schräge zu jedem dieser Teile zu gelangen?

Antworten:


10

Dies kann mit einer Faltung der Abstandstransformation erreicht werden.

Verwenden Sie eine Abstandstransformation am Rand der Maske. Setzen Sie dann einen Schwellenwert für diese Abstandstransformation, um Werte zu entfernen, die einen gewissen Abstand überschreiten. Ich denke, das Geheimnis, um die Schattierung zu erhalten, besteht darin, das Ergebnis der Distanztransformation mit einem Kernel zu falten, der ungefähr so ​​aussieht:

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

Damit sollten Sie in die richtige Richtung starten:

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

Bildbeschreibung hier eingeben

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

Bildbeschreibung hier eingeben

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

Bildbeschreibung hier eingeben

    waitKey(0);
}

Die sehen toll aus! Die mit der Weichzeichnung sieht aus wie eine Unschärfe, aber wie würde ich die "Glatte Abschrägung" daraus machen?
Shedokan

Ich glaube, Smooth Bevel verwischt die Distanzmaske vor der Faltung und Soften verwischt das Ergebnis nach der Faltung.
Matt M.

4

Bevel and Emboss von Photoshop funktioniert vorhersehbar:

1) Berechnen Sie eine Abstandstransformation in einem temporären 8-Bit-Einzelkanalbild

  • Chisel verwendet die euklidische Distanztransformation mit einer Fasenmetrik (je nach Größe 3x3, 5x5 oder 7x7). Sie können eine exakte euklidische Abstandstransformation verwenden, wenn Sie möchten. Ich bevorzuge die von Meijster, da sie geglättet werden kann ("Ein allgemeiner Algorithmus zum Berechnen von Abstandstransformationen in linearer Zeit", MEIJSTER).

  • Smooth Bevel verwendet eine Fasen-5-7-11-Abstandstransformation, gefolgt von zwei Anwendungen einer Rahmenunschärfe, um die Reliefkarte zu erstellen.

2) Wenden Sie Bump-Mapping auf das Transformationsbild für den Zwischenabstand an. Blinns ursprüngliche Technik ist geeignet.

3) Zum Weichzeichnen können Sie eine Faltung der Oberflächennormalen durchführen oder sie mit einem Kernel filtern.

4) Unter Verwendung der Reliefkarte werden die Oberflächennormalen mit der globalen Lichtquelle kombiniert, um die Beleuchtungsstärke als einen Wert von -1 bis 1 zu berechnen, wobei negative Werte Schatten sind, positive Werte Glanzlichter sind und der Absolutwert die Größe des Lichts ist Quelle.

5) Zwei temporäre 8-Bit-Einzelkanalbilder werden berechnet, eines aus den Lichtintensitäten und das andere aus den Schatten. Von da an ist es ganz einfach, die einzelnen Masken zu verwenden, um die Ebene mithilfe von Farbe, Mischmodus und Deckkraft einzufärben - eine Maske für die Lichter und die andere für die Schatten.

Visual Basic-Quellcode zum Implementieren einiger davon finden Sie hier:

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

Bitte besuchen Sie mein Open Source LayerEffects-Projekt, um mehr zu erfahren:

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

Ich hoffe das hilft jemandem.


Vielen Dank, ich interessiere mich sehr für die von Ihnen erwähnte Gaußsche Distanztransformation. Sind Ihnen Codes bekannt? Ich kann Formeln nicht gut lesen. :(
Shedokan

Ich habe nichts über die GDT gefunden, außer den Informationen, die ich bereits gepostet habe.
Vinnie Falco

Was meinen Sie mit "2) Bump-Mapping auf Distanztransformationsbild anwenden"? Die Entfernungstransformation gibt Entfernungen an (1 Zahl für jedes Pixel), während die Bump-Zuordnung Normalen erfordert (2 Zahlen für jedes Pixel) ... Sind Sie sicher, dass Sie wissen, wovon Sie sprechen?
Ivan Kuckir

@IvanKuckir Ich hätte klarer sein sollen - eine Oberflächennormale kann berechnet werden, indem die Abstandstransformation als Höhenkarte behandelt und dx / dy aus benachbarten vertikalen und horizontalen Werten berechnet wird. Diese beiden Zahlen geben die für die Bump-Zuordnung erforderliche Norm an.
Vinnie Falco
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.