Closed VittorioAccomazzi closed 3 years ago
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:
Implemented the Difference of Gaussian for define the contours in the image. here are the results with:
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:
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.
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!)
}
.....
}
.....
}
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.
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++]
}
Implemented the LoG along the major eigenvector direction, as described in Image and Video Abstraction by Coherence-Enhancing Filtering with the following variation:
Here below are the image obtained from the LoG filter, which indeed edges. Sigma is 1.5, as suggested in the article
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
Changing the painter algorithm entirely, as follow:
The result provides a nice level of abstraction in several images, however not entirely consistent. Notice that:
const numSteps = 6
......
if( this.step < numSteps) {
[this.lImage, this.aImage, this.bImage] = TensorDirSmoothing.Run(this.lImage!, this.aImage!, this.bImage!,1.5,tRelax) as [ ImageFloat32, ImageFloat32, ImageFloat32]
let tf = TensorGenerator.Run(this.lImage!, this.aImage!, this.bImage!, 1,tRelax)
this.lImage = TensorShock.Run(this.lImage!, tf, 1.5, 5, 1) as ImageFloat32
outCanvas = CanvasUtil.fromLab(this.lImage, this.aImage, this.bImage)
}
The pictures used above are the ones looking the worst:
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:
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
identify the filtering approach which allows to perform a consistent and pleasing abstraction. Good source of information :