Algoritma bitmap alpha bevel?

14

Saya ingin membuat algoritma yang menambahkan efek bevel ke bitmap menggunakan alfa sebagai peta benjolan.

Bagaimana saya melakukan sesuatu seperti ini? Saya telah mencoba pencahayaan specular tetapi saya hanya mendapatkan highlight dan bukan bayangan.

Inilah efek yang saya bicarakan (dibuat menggunakan Photoshop): masukkan deskripsi gambar di sini

Semua ini dilakukan dengan menggunakan size: 30px(Kedalaman bevel dari kontur bitmap) angle 130,, altitude 50.

Dari kiri ke kanan, atas ke bawah:

  1. Pahat keras bevel
  2. Pahat Bevel Lembut
  3. Bevel halus
  4. Pahat Keras dengan soften: 16px- bevel kabur?

Saya mencoba membuat masing-masing efek ini, bagaimana cara membuat bevel dasar? dan apa yang saya perlukan untuk masing-masing dari bevel itu

Shedokan
sumber

Jawaban:

10

Ini dapat dicapai dengan konvolusi transformasi jarak.

Gunakan transformasi jarak di tepi topeng. Kemudian ambang transformasi jarak ini untuk menghapus nilai di luar jarak tertentu. Saya pikir rahasia untuk mendapatkan naungan adalah dengan menggabungkan hasil transformasi jarak dengan kernel yang terlihat seperti ini:

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

Ini akan membantu Anda memulai ke arah yang benar:

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

masukkan deskripsi gambar di sini

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

masukkan deskripsi gambar di sini

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

masukkan deskripsi gambar di sini

    waitKey(0);
}
Matt M.
sumber
Itu terlihat luar biasa! Yang dengan melembut terlihat seperti kabur, tapi bagaimana aku membuat "Bevel Halus" dari mereka?
Shedokan
Saya percaya Smooth Bevel mengaburkan masker jarak sebelum konvolusi, dan Soften mengaburkan hasilnya setelah konvolusi.
Matt M.
4

Bevel dan Emboss Photoshop berfungsi dengan baik:

1) Hitung transformasi jarak dalam gambar saluran tunggal 8-bit sementara

  • Pahat menggunakan Transformasi Jarak Euclidean dengan metrik Chamfer (3x3, 5x5, atau 7x7 tergantung pada ukuran). Anda dapat menggunakan transformasi jarak euclidean yang tepat jika Anda mau, saya lebih suka yang dari Meijster karena dapat dibuat anti-alias ("Algoritma Umum untuk Menghitung Transformasi Jarak dalam Waktu Linear", MEIJSTER).

  • Smooth Bevel menggunakan transformasi jarak 5-7-11 Chamfer diikuti oleh dua aplikasi blur kotak, untuk menghasilkan peta benjolan.

2) Menerapkan pemetaan singkat ke gambar transformasi jarak menengah. Teknik asli Blinn cocok.

3) Untuk pelunakan, Anda dapat melakukan konvolusi pada normals permukaan atau Anda dapat memfilternya menggunakan kernel.

4) Dengan menggunakan bump map, normals permukaan digabungkan dengan sumber cahaya global untuk menghitung intensitas pencahayaan sebagai nilai -1 hingga 1 di mana nilai negatif adalah bayangan, nilai positif adalah highlight, dan nilai absolut adalah besarnya cahaya sumber.

5) Dua gambar sementara saluran tunggal 8-bit dihitung, satu dari intensitas sorotan dan yang lainnya dari bayangan. Dari sana adalah hal yang sepele untuk menggunakan setiap topeng untuk mewarnai lapisan menggunakan warna, mode campuran, dan opacity - satu topeng untuk highlight dan yang lainnya untuk bayangan.

Kode sumber Visual Basic untuk mengimplementasikan beberapa hal ini dapat ditemukan di sini:

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

Silakan kunjungi proyek LayerEffects open source saya untuk mempelajari lebih lanjut:

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

Saya harap ini membantu seseorang.

Vinnie Falco
sumber
Terima kasih, saya sangat tertarik dengan Gaussian Distance Transform yang Anda sebutkan, apakah Anda mengetahui ada kode yang tersedia? Saya tidak bisa membaca rumus dengan baik. :(
Shedokan
Saya belum menemukan apa pun tentang GDT, selain informasi yang sudah saya posting.
Vinnie Falco
Apa yang Anda maksud dengan "2) Menerapkan pemetaan benjolan untuk mengubah jarak gambar"? Transformasi jarak memberi jarak (1 angka untuk setiap piksel), sedangkan pemetaan Bump membutuhkan nilai normal (2 angka untuk setiap piksel) ... Apakah Anda yakin tahu apa yang Anda bicarakan?
Ivan Kuckir
@IvanKuckir Saya seharusnya lebih jelas - permukaan normal dapat dihitung dengan memperlakukan transformasi jarak sebagai peta tinggi dan menghitung dx / dy dari nilai-nilai vertikal dan horizontal yang berdekatan. Dua angka ini memberikan normal yang diperlukan untuk pemetaan bump.
Vinnie Falco