[Résolu] Resample d'image anti aliasé => interpolation BICUBIC

Resample d'image anti aliasé => interpolation BICUBIC [Résolu] - Java - Programmation

Marsh Posté le 03-03-2005 à 15:23:03    

Bon, ça fait 3 heures que j'essaye de redimentionner une image sans que ça devienne crade quand je la réduise.
 
J'avais commencé avec AffineTransformOp, puis pas satisfait je me suis dit qu'avec JAI ce serait mieux, et non rien n'y fait quand j'agrandis ça va c'est assez beau, mais quand je réduis, j'ai l'impression que l'anti aliasing marche pas.
 
Voilà le code sans JAI :
 


// dans le doute j'ai tout mis à fond
renderHints=new RenderingHints(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
renderHints.put(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
renderHints.put(RenderingHints.KEY_DITHERING,RenderingHints.VALUE_DITHER_ENABLE);
renderHints.put(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
 
//.....
 
 
 
 
AffineTransform tr=new AffineTransform();
tr.scale((double)finalw/(double)w,(double)finalh/(double)h);
AffineTransformOp rop=new AffineTransformOp(tr,renderHints);
return rop.filter(pre, ret);


 
et en fait quand je le fais avec JAI le rendu est quasiment pareil  
 


ParameterBlockJAI pb = new ParameterBlockJAI("scale" );
pb.addSource(loadedImage);
pb.setParameter("xScale",(float)zoomFactor);                
pb.setParameter("yScale",(float)zoomFactor);                
pb.setParameter("xTrans",0f);                          
pb.setParameter("yTrans",0f);                            
pb.setParameter("interpolation",new InterpolationBicubic2(8));
PlanarImage newImage= JAI.create("scale", pb, renderHints); // le même renderHints qu'avant


 
donc là je sais pas... si quelqu'un a déjà fait ça...


Message édité par raytaller le 04-03-2005 à 12:32:50
Reply

Marsh Posté le 03-03-2005 à 15:23:03   

Reply

Marsh Posté le 03-03-2005 à 15:44:38    

les preuves :
 
affine transform java de base :
http://tom.rethaller.free.fr/vrac/antialiasing/affineTransform.jpg
 
interpolation biliéaire JAI:
http://tom.rethaller.free.fr/vrac/antialiasing/bilinear.jpg
 
interpolation bicubique JAI :
http://tom.rethaller.free.fr/vrac/antialiasing/bicubic.jpg
 
interpolation bicubique2 JAI :
http://tom.rethaller.free.fr/vrac/antialiasing/bicubic2.jpg
 
photoshop :
http://tom.rethaller.free.fr/vrac/antialiasing/toshop.jpg
 
edit : c'est surtout sur la bretelle qu'on le voit.
c'est pas que je suis chiant, mais je fais ça pour un graphiste qui s'est plaint de ce défaut


Message édité par raytaller le 03-03-2005 à 15:46:36
Reply

Marsh Posté le 03-03-2005 à 15:52:37    

J'aurais mis :

AffineTransformOp rop=new AffineTransformOp(tr, RenderingHints.VALUE_INTERPOLATION_BICUBIC);


Je pense que c'est suffisant

Reply

Marsh Posté le 03-03-2005 à 16:14:06    

tu voulais dire :
 
AffineTransformOp rop=new AffineTransformOp(tr, new RenderingHints(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC));
 
 ?
 
 
Ça reste pixélisé... en fait, ces méthodes d'interpolation elles marchent très bien quand il s'agit d'agrandir mais là...
 
Moi j'y connais pas énorme en traitement d'image, y'apa une histoire d'AntiAliasing ?

Reply

Marsh Posté le 03-03-2005 à 16:14:43    

Non, je dis bien

AffineTransformOp rop=new AffineTransformOp(tr, RenderingHints.VALUE_INTERPOLATION_BICUBIC);


 
Pas besoin de construire un objet RenderingHints :??:

Reply

Marsh Posté le 03-03-2005 à 17:23:02    

Eclipse m'a soufflé que le constructeur AffineTransformOp(AffineTransform, Object) n'était pas défini.

Reply

Marsh Posté le 03-03-2005 à 18:31:29    

Bon, j'ai fait des comparaisons et voilà, j'ai quasiment au pixel près la même image que quand je rescale en NEAREST_NEIGHBOR dans photoshop.
 
Donc, j'en conclus que le rescale se fait effectivement en NEAREST_NEIGHBOR là c'est vraiment flagrant.
 
 
 
Sinon, j'ai essayé en mettant un blur avant le rescale c'est déjà moins pire mais ça ne fonctionne que si on connait déjà en gros la taille de l'image à redimentionner.
 
 
Est-ce que je devrais essayer d'appliquer un algo moi même ? (un truc tout fait j'y connais rien)
Ça me parraît suspect que jamais personne n'ait eu à redimentionner une image en petit et en net en java.
 
 

Reply

Marsh Posté le 03-03-2005 à 18:35:25    

Non, normalement on peut y arriver. C'est étrange qu'en mode Bicubic ça ne fonctionne pas :heink:

Reply

Marsh Posté le 03-03-2005 à 18:48:44    

bah je pense aussi.. mais là c'est même pas comme si ça ouvait venir de l'enregistrement JPEG parce que même avant compression affiché dans un JPanel c'est pareil, y'a des escaliers.  
Et ce juste avec un :
 

Code :
  1. AffineTransform tx = new AffineTransform();
  2.         tx.scale(zoomFactor, zoomFactor);
  3.         AffineTransformOp op = new AffineTransformOp(tx,
  4.                 AffineTransformOp.TYPE_BICUBIC);
  5.         sizedImage=op.filter(loadedImage,null);

Reply

Marsh Posté le 03-03-2005 à 18:50:25    

Et puis c'est pas pour dire mais JAI c'est un de ces bordel :D

Reply

Marsh Posté le 03-03-2005 à 18:50:25   

Reply

Marsh Posté le 03-03-2005 à 23:38:12    

JAI c'est pas "déprecié" depuis qu'il y a a peu pres la meme chose dans le jdk1.4?  
 
et sinon pour la visibilité des defauts, moi c'est les yeux et la bouche qui me choquent ;)
 
et sinon le sujet m'interesse aussi... j'avais fait un jour un sujet similaire, mais pour le texte :)
 
edit: on y avait pas trouvé de bonne réponse pour l'anti alias, mais bon voilà: http://forum.hardware.fr/forum2.ph [...] 155&cat=10


Message édité par the real moins moins le 03-03-2005 à 23:39:50

---------------
Hey toi, tu veux acheter des minifigurines Lego, non ?
Reply

Marsh Posté le 04-03-2005 à 01:03:56    

bah.. JAI en fait ça me ferait plaisir que ce soit déprécié, c'est vraiment un bordel infâme.
 
sinon, cette tronche pour tes String antialiasées ça t'irait pas ?
 
http://tom.rethaller.free.fr/vrac/Opale_preview1.png
 
c'est le truc d'emploi du temps sur lequel je bosse et avec un simple RenderingHints.VALUE_ANTIALIAS_ON ça me fait un truc assez propre je trouve
 
mais ce qui me tue c'est que les 3 modes d'interpolation en java c'est NEAREST, BILINEAR et BICUBIC et que.... dans photoshop c'est exactement les mêmes.
enfin, ce qui me tue c'est justement que le BICUBIC de java corresponde au NEAREST de photoshop, tandis que le NEAREST de java ne correspond à peu près à rien.
 
c'est pas possible, c'est forcément les mêmes algos.. je comprends pas.


Message édité par raytaller le 04-03-2005 à 01:05:24
Reply

Marsh Posté le 04-03-2005 à 09:12:43    

raytaller a écrit :

bah.. JAI en fait ça me ferait plaisir que ce soit déprécié, c'est vraiment un bordel infâme.
 
sinon, cette tronche pour tes String antialiasées ça t'irait pas ?
 
http://tom.rethaller.free.fr/vrac/Opale_preview1.png
 
c'est le truc d'emploi du temps sur lequel je bosse et avec un simple RenderingHints.VALUE_ANTIALIAS_ON ça me fait un truc assez propre je trouve
 
mais ce qui me tue c'est que les 3 modes d'interpolation en java c'est NEAREST, BILINEAR et BICUBIC et que.... dans photoshop c'est exactement les mêmes.
enfin, ce qui me tue c'est justement que le BICUBIC de java corresponde au NEAREST de photoshop, tandis que le NEAREST de java ne correspond à peu près à rien.
 
c'est pas possible, c'est forcément les mêmes algos.. je comprends pas.


 
De ce que tu nous montre là, j'ai l'impression que c'est pas du "bicubique filtré" comme dirait Monsieur GDIPlus. C'est à dire qu'il ne fait le bicubique que sur les pixels immédiatement voisins du pixel source. Et si ton image est grande, ça ignore complètement une grosse partie des pixels alentour..
 
Si tu le peux, essaye de faire du bicubique par increments (c'est à dire faire un resize en 100x100, puis 80x80, pui 60x60, etc.). D'ailleurs, même sous Photoshop, c'est recommandé (ça s'appelle le pyramidal bicubic je crois).
 

Reply

Marsh Posté le 04-03-2005 à 09:58:14    

ah, tiens c'est une bonne idée ça :)
ouais, je vais essayer ça, les réductions de 1/2 ça se passe bien, je vais utiliser ça comme pas.
 
sinon, j'en avais eu une d'idée, j'ai testé sous photoshop et ça a l'air pas mal : mettre un blur avant de redimentionner
 
en fait, si l'image est réduite par plus que 3, je pensais faire une convolution 3*3, réduite par 4, une convolution 4*4 etc...
 
même si j'ai pas fait ça précisément, sous photoshop, faire un blur puis un rescale en NEAREST c'est déjà mile fois mieux que ce que j'ai avec java.
 
 
mais là je vais tenter de le faire par étapes en effet.
 
sinon, on m'a conseillé imageMagik mais le wrapper pour java a pas de vraie doc, et j'ai vu nulle part qu'on choisissait la méthode de resample...

Reply

Marsh Posté le 04-03-2005 à 10:37:51    

Si tu fais une convolution 3*3, il faut réduire par 2. En partant du principe que tu utilises ce noyau là:

1 2 1
2 4 2
1 2 1


(C'est basé sur le triangle de pascal, qui permet d'avoir une bonne approximation des facteurs à appliquer pour calculer un gaussian blur)
 
 
D'un point de vue théorique, le blur de Photoshop passe bien, parce qu'il ne garde que les basses fréquences, ce qui est précisemment ce qui te manque dans ton resize. Par contre, le blur est gaussien et non pas uniforme: il utilise une courbe en forme de "cloche" pour calculer les facteurs.  
 
Rien ne t'empêche de le faire toi-même, et en plus, ça t'apprendra beaucoup. Tu as juste besoin de savoir 2 choses:

  • Le gaussian blur est dit "séparable", ça veut dire que tu peux l'appliquer d'abord verticalement, puis horizontalement (ou l'inverse). Ca te fait du 2*N au lieu de faire du N².
  • Et les facteurs à calculer sont comme ça il me semble:
Code :
  1. double r = la taille de la gaussienne voulue;
  2. double d = 5*radius +1;// taille du vecteur de convolution
  3. pour i = 1 à d
  4.   vecteur[i]= exp(d²/r²) * exp(- i²/r²)


Message édité par Lam's le 04-03-2005 à 10:39:13
Reply

Marsh Posté le 04-03-2005 à 10:46:14    

Lam's a écrit :

Si tu fais une convolution 3*3, il faut réduire par 2. En partant du principe que tu utilises ce noyau là:

1 2 1
2 4 2
1 2 1


(C'est basé sur le triangle de pascal, qui permet d'avoir une bonne approximation des facteurs à appliquer pour calculer un gaussian blur)
 
 
D'un point de vue théorique, le blur de Photoshop passe bien, parce qu'il ne garde que les basses fréquences, ce qui est précisemment ce qui te manque dans ton resize. Par contre, le blur est gaussien et non pas uniforme: il utilise une courbe en forme de "cloche" pour calculer les facteurs.  
 
Rien ne t'empêche de le faire toi-même, et en plus, ça t'apprendra beaucoup. Tu as juste besoin de savoir 2 choses:

  • Le gaussian blur est dit "séparable", ça veut dire que tu peux l'appliquer d'abord verticalement, puis horizontalement (ou l'inverse). Ca te fait du 2*N au lieu de faire du N².
  • Et les facteurs à calculer sont comme ça il me semble:
Code :
  1. double r = la taille de la gaussienne voulue;
  2. double d = 5*radius +1;// taille du vecteur de convolution
  3. pour i = 1 à d
  4.   vecteur[i]= exp(d²/r²) * exp(- i²/r²)



 
ah ouais, j'aurais juré que le gauss ça se faisait en fonciton de la distance géométrique de chaque pixel (donc un truc qui dépend des x et des y)
 
mais là, j'ai appliqué ce que tu me conseillais, et ça marche je dirais à peu près parfaitement... en plus c'est simple comme idée mais j'y avais même pas pensé, vraiment là ça me soulage
je te remercie avec force  :sweat:  

Reply

Marsh Posté le 04-03-2005 à 10:51:17    

raytaller a écrit :

ah ouais, j'aurais juré que le gauss ça se faisait en fonciton de la distance géométrique de chaque pixel (donc un truc qui dépend des x et des y)


Bah oui, mais comme je t'ai dit, il est séparable, donc d'abord tu l'appliques en longueur (donc ça dépend effectivement de la distance horizontale), puis en largeur (donc ça dépend de la distance verticale).  
 
Ceci dit, là où j'utilise i², tu peux utiliser "exp( -(i²+j²)/d²)" si tu souhaites calculer le noyau complet.
 

Reply

Marsh Posté le 04-03-2005 à 10:52:40    

Et sinon, en passant par un objet Graphics2D et la méthode drawImage qui peut faire du rescaling, et en plus qui peut filtrer la chose ?

Reply

Marsh Posté le 04-03-2005 à 11:58:02    

raytaller >> ben si en fait c'est pas mal ton résultat. me rappelle même plus sur quoi je m'étais basé pour me dire que ça vallait la peine de creuser !? j'avais du faire des tests, mais ché plus où :D


---------------
Hey toi, tu veux acheter des minifigurines Lego, non ?
Reply

Marsh Posté le 04-03-2005 à 12:25:57    

the real moins moins a écrit :

raytaller >> ben si en fait c'est pas mal ton résultat. me rappelle même plus sur quoi je m'étais basé pour me dire que ça vallait la peine de creuser !? j'avais du faire des tests, mais ché plus où :D


 
Si ça t'intéresse, j'avais posté ça sur un autre topic, elles ressemblent à rien ces méthodes (et puis c'est vrai que le français bof bof mais là c'était de circonstance) mais elles dessinent une String dans un rectangle, en gardant le ratio de la Font et en centrant si y'a besoin.
Mine de rien, j'm'en sers pas mal :
 
http://forum.hardware.fr/forum2.ph [...] 16#t996923
 
 
Lam's > bah oui, chuis con, la distance au carré c'est rien d'autre qu'une addition
FlorentG > bah en fait, quelle que soit la méthode utilisée, un rescale direct fait moche. En fait, il faut faire comme Lam's a dit et là c'est nickel


Message édité par raytaller le 04-03-2005 à 12:27:06
Reply

Marsh Posté le 04-03-2005 à 12:26:48    

C'est marrant, parce que moi j'avais déjà fait des rescale, et ils n'étaient pas moche. Et sans passer par un bordel monstre :heink:

Reply

Marsh Posté le 04-03-2005 à 12:31:08    

bah figure toi que je m'en étais même pas rendu compte, en fait, c'est en comparant avec le rescale de photoshop que c'est flagrant.
 
et puis tant que le facteur d'échelle est supérieur à 1/2 ça se voit pas, mais comme l'a dit Lam's c'est sûrement que le BICUBIC de java ne s'occupe que des pixels proches et dans le cas d'un facteur d'échelle minus (là c'était le cas, j'avais en moyenne du 1/10) plein de pixels sont ignorés.
 
en fait là pour avoir vraiment un beau rendu, je l'ai fait par étapes de 0.875 mais même avec 0.75 c'est déjà bien

Reply

Marsh Posté le 04-03-2005 à 12:32:53    

J'vais faire des essais ce soir :)

Reply

Marsh Posté le 04-03-2005 à 12:33:58    

bah si tu trouves un truc plus rapide, je prends :)

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed