VittorioAccomazzi / Artist

The artist which will paint your pictures before your eyes !
0 stars 0 forks source link

Experimentation #4

Closed VittorioAccomazzi closed 3 years ago

VittorioAccomazzi commented 3 years ago

identify the filtering approach which allows to perform a consistent and pleasing abstraction. Good source of information :

VittorioAccomazzi commented 3 years ago

Gaussian Bilateral Filtering

Implemented the Gaussian bilateral filter which is mention by all the paper above. The implementation is straightforward, and tested on RGB, HSV and Lab colour spaces. Here is an example in Lab with:

VittorioAccomazzi commented 3 years ago

DoG for contours

Implemented the Difference of Gaussian for define the contours in the image. here are the results with:

VittorioAccomazzi commented 3 years ago

Color Quantization

Implemented a simple colour quantization, taken from Real-time video abstraction but without the gradient terms, since it seems smooth enough. Here is the quantization at 12 values, and it is done on the luminosity component of the Lab decomposition only. the image on the left is smoothed with a bilateral Gaussian filter and the DoG has been overlaid: Screen Shot 2021-02-21 at 1 01 47 PM Screen Shot 2021-02-21 at 1 01 12 PM

VittorioAccomazzi commented 3 years ago

Tensor Filter

As outlined in Image and Video Abstraction by Coherence-Enhancing Filtering the image structure tensor can capture very effectively the variation of the image, and so relevant details.

Simple Approach

Implemented a simple 'brute force' approach : simple smoothing on the along the direction of the minor eigenvector:

the code used is the following:


const numSteps = 5
const scaleStd = 2
const rangeStd = 2
const scaleDog = 3

export default class Painter {

....

    next() : SeqCanvas | null {
        let outCanvas = null

        if( this.step < numSteps) {
            [this.lImage, this.aImage, this.bImage] = TensorFilter.Run(this.lImage!, this.aImage!, this.bImage!,1) as [ ImageFloat32, ImageFloat32, ImageFloat32]
            [this.lImage, this.aImage, this.bImage] = TensorFilter.Run(this.lImage!, this.aImage!, this.bImage!,1) as [ ImageFloat32, ImageFloat32, ImageFloat32]
            [this.lImage, this.aImage, this.bImage] = BilateralFilter.Run(this.lImage!, this.aImage!, this.bImage!, scaleStd, rangeStd) as [ ImageFloat32, ImageFloat32, ImageFloat32]
            outCanvas = CanvasUtil.fromLab(this.lImage, this.aImage, this.bImage)
        } else if ( this.step === numSteps ){
            this.luminosityQuantization()
            outCanvas = CanvasUtil.fromLab(this.lImage!, this.aImage!, this.bImage!)
        }

        .....
    }
.....

}
VittorioAccomazzi commented 3 years ago

Painter Improvement

Adding tensor filter

The tensor filter does improves the abstraction of the hair, even if the implementation is still very simplistic, as shown in the images above. Using the code posted above.

Remove the border line

instead of adding the dark border line, added the original image with the same weights, the code is the following:

    private overlayDog( inCanvas : SeqCanvas) {
        let dogImage = this.dImage!
        let width = dogImage.width
        let height= dogImage.height
        let nPixels= width*height
        let dogPixels= dogImage.imagePixels
        let orgPixels= this.oImage.data // original image
        let ptr=0
        for( let p=0; p<nPixels; p++ ){
            let weight = dogPixels[p]
            inCanvas.data[ptr] = weight * inCanvas.data[ptr]+(1-weight)*orgPixels[ptr++]
            inCanvas.data[ptr] = weight * inCanvas.data[ptr]+(1-weight)*orgPixels[ptr++]
            inCanvas.data[ptr] = weight * inCanvas.data[ptr]+(1-weight)*orgPixels[ptr++]
        }

Screen Shot 2021-02-23 at 9 08 25 PM

VittorioAccomazzi commented 3 years ago

Tensor Shock Filter

Implemented the LoG along the major eigenvector direction, as described in Image and Video Abstraction by Coherence-Enhancing Filtering with the following variation:

Tensor LoG

Here below are the image obtained from the LoG filter, which indeed edges. Sigma is 1.5, as suggested in the article tensor LoG image test2 tensor LoG image test1

Tensor Shock

Here is the shock filter which uses the log above. The computation is done with the L component in Lab space as follow:

       let [lImg, aImg, bImg] = CanvasUtils.toLab(toSeqCanvas(canvas))

        GaussianFilter.Run(lImg,1)
        let tf = TensorGenerator.Run(lImg, aImg, bImg, 1) 
        let flt= TensorShock.Run(lImg, tf, 2, 0.01, 2) as ImageFloat32

tensor Shock test1 tensor Shock test2

VittorioAccomazzi commented 3 years ago

Painter Variation

Changing the painter algorithm entirely, as follow:

The result provides a nice level of abstraction in several images, however not entirely consistent. Notice that:

And some of the artefact created are consistent with what I see here. however some of the images with fur head shots are looking quite good, but quite inconsistent: Screen Recording 2021-03-02 at 8 47 10 PM Screen Shot 2021-03-02 at 9 06 13 PM

VittorioAccomazzi commented 3 years ago

Final Decision : Tensor and Bilateral Painters

Based on this experimentation the decision is to generate to painters:

Here are comparisons, on the left the tensor image, on the right the bilateral

Screen Shot 2021-03-05 at 9 32 00 PM Screen Shot 2021-03-05 at 9 34 55 PM