REDIMENSIONNEMENT XBR

cs_pseudo3 Messages postés 268 Date d'inscription mardi 24 juillet 2007 Statut Membre Dernière intervention 2 février 2021 - 11 août 2012 à 13:44
cs_pseudo3 Messages postés 268 Date d'inscription mardi 24 juillet 2007 Statut Membre Dernière intervention 2 février 2021 - 25 août 2012 à 09:13
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/54505-redimensionnement-xbr

cs_pseudo3 Messages postés 268 Date d'inscription mardi 24 juillet 2007 Statut Membre Dernière intervention 2 février 2021 1
25 août 2012 à 09:13
Bonjour Barbichette,

"Pour le problème de rotation, c'est que ton programme de rotation que tu as utilisé pour faire 22° provoque un flou car il interpole déjà les pixels de l'image destination. Cette algorithme va donc bien marcher, mais l'image original n'est déjà plus très "propre".
... Exact, et ce léger flou additionnel ne facilite pas la détection des contours à XBR ce qui permet de détecter ce point faible du XBR.

Mais comme je me suis permis de critiquer avec mon histoire des 22° je suis parti dans un casse-tête pour essayer de trouver un remède mais c'est pas encore gagné... (je suis parti sur une piste de recherche des lignes topographiques des niveaux de gris considérés représenter la luminosité équivalente : c'est plus rapide à calculer que de passer par des RgbToHSV ou RGBToHSL).

"Il existe des algorithmes (comme "Canny edge detector") qui permettent de détecter les contour dans une image. (Et je vais essayé de faire un truc)... Bon, je vais surement revenir avec de la détection Canny..."
... Très bonne idée.

A+.
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
23 août 2012 à 18:26
@Pseudo3:
Non, je ne vais pas t'envoyer balader.
Par contre, je n'ai clairement pas les compétences universitaires nécessaire à une telle entreprise.
Une petite piste quand-même si quelqu'un tombe ici.
Il existe des algorithmes (comme "Canny edge detector") qui permettent de détecter les contour dans une image. (Et je vais essayé de faire un truc)
En mélangeant cet algo de recherche des contours avec un algo comme celui ci-dessus qui, pour résumer, provoque un dégradé plus ou moins rapide en fonction des contours, on devrait pouvoir faire un truc sympas...

Pour le problème de rotation, c'est que ton programme de rotation que tu as utilisé pour faire 22° provoque un flou car il interpole déjà les pixels de l'image destination.
Cette algorithme va donc bien marcher, mais l'image original n'est déjà plus très "propre".

@Cirec:
Merci pour les modifs.
J'avoue avoir faite un peu vite avant mes vacances et oublié de supprimer des morceaux de codes inutiles...

Bon, je vais surement revenir avec de la détection Canny...
cs_pseudo3 Messages postés 268 Date d'inscription mardi 24 juillet 2007 Statut Membre Dernière intervention 2 février 2021 1
19 août 2012 à 16:00
Bonjour,

Le résultat est effectivement bluffant avec l'image plus "parlante". Par contre celle-ci place xBR dans les conditions les plus favorables pour un rendu visuel optimal.
J'ai donc pris une copie de l'image "parlante" et je lui appliqué (sournoisement) une rotation d'ensemble de 22 degrés vers la gauche puis j'ai agrandi celle-ci à 400% avec xBR4 : bin les gars le rendu visuel n'est plus "bluffant" du tout : ça ressemble à une toile sur laquelle le peintre s'est obstiné à utiliser un pinceau quasi-sec qui ne laisse que des traces.

D'où une question : Est-il possible d'adapter le code pour améliorer davantage le rendu visuel lorsque xBR rencontre un bord incliné à mi-chemin entre les angles 0-45°, 45-90°, 90-135° c'est à dire incliné à 22,5°, 67,5 ° et 112,5° ???
(je m'attends à ce que Barbichette m'envoie balader, mais ça ne coûte rien de poser la question ... on ne sait jamais).

Bon dimanche et A+.
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
18 août 2012 à 14:24
Bravo Barbichette,

très bon travail ... un seul regret ... l'image choisit ne rend pas hommage au code

je me suis donc permis de faire une petite mise à jour :
(retrait du code mort et ajout d'une image plus "parlante")

le résultat est bluffant ... bravo 10/10
laoubiadel Messages postés 9 Date d'inscription jeudi 26 février 2009 Statut Membre Dernière intervention 16 mai 2012
14 août 2012 à 14:32
merci .............................................
cs_pseudo3 Messages postés 268 Date d'inscription mardi 24 juillet 2007 Statut Membre Dernière intervention 2 février 2021 1
13 août 2012 à 13:59
Re-salut,

"Pour un redimensionnement avec un facteur quelconque" : pour ma part c'est réglé avec ma bidouille de code citée plus haut. Pourquoi se casser la tête, un peu de repos pendant les vacances ça fait du bien.

A+.
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
13 août 2012 à 13:17
c'est justement le cas, les 20 voisins sont les voisins dans l'image original.
Pour un redimensionnement avec un facteur quelconque, je vais regarder comment interpoler le carré de destination qui n'est plus pile poil 2x2 ou 4x4 mais par exemple 1,28x1,28 a cheval sur plusieurs pixels...

(Et dire que je suis en vacances et que je travail plus qu'au boulot...)

A +
cs_pseudo3 Messages postés 268 Date d'inscription mardi 24 juillet 2007 Statut Membre Dernière intervention 2 février 2021 1
13 août 2012 à 13:06
Re-salut,

A propos de "Il traite chaque pixel de l'image original et le compare aux 20 voisins" :

Ce qui m'intrigue : voici un schéma d'agrandissement où chaque lettre majuscule représente un pixel de couleur connue

AB <- ici 4 pixels contigüs du BiMap-Original dont les centres forment un carré de 1x1 pixel
CD

et ici l'agrandissement où les quelques tirets '-' représentent les pixels de l'image agrandie dont on cherche les couleurs interpolées entre celles de A,B,C,D :

A------B
--------
--------
C------D

donc s'il traite chaque pixel de l'image originale et le compare aux 20 voisins, ces voisins sont forcément des pixels situés à l'extérieur du carré ABCD dont les pixels sont contigüs, et cela ne facilite pas la compréhension des explication du lien cité par Barbichette. On dirait presque que l'auteur a mis au point son raisonnement en se plaçant dans le cas d'une réduction pour l'appliquer ensuite à l'agrandissement.
On comprendrait mieux s'il avait tenu compte des pixels situés à l'extérieur de ABCD pour déterminer les paramètres d'une courbe de variation à utiliser pour calculer les couleurs des pixels situés à l'intérieur.

A+.
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
13 août 2012 à 12:05
Oupsss.. j'ai effacé par erreur un morceau de texte...
"...4 matrices qui sont dans l'ordre",
...4 matrices qui sont dans l'ordre, 45°+135°, 45°, 135°, 90°.
Je vous conseille de regarder le lien que j'ai mis dans la présentation pour comprendre ces angles...
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
13 août 2012 à 12:03
Barbichette n'a que recopié un code en C++.
Pour ceux qui veulent aller plus loin, je vais donner quelques explications que j'ai comprises sur cette algo.
Il traite chaque pixel de l'image original et le compare aux 20 voisins (carré de 5*5 sans les coins).
Si il détecte un bord (une différence de couleur suffisante) il maintient ce bord en appliquant une des 4 matrices qui sont dans l'ordre.
Sinon, il fait un simple flou entre le pixel et ces voisins en diagonales
else if le<=li then
ALPHA_BLEND_128_W(E[N3], ifthen(df(PE,PF) <= df(PE,PH),PF,PH));
comme la recherche des bords est symétrique, dans le programme, on cherche les bords vers le cadran du bas à droite, puis on recommence en faisant une rotation.
cs_MAURICIO Messages postés 2106 Date d'inscription mardi 10 décembre 2002 Statut Modérateur Dernière intervention 15 décembre 2014 5
13 août 2012 à 11:13
Trop fort notre Barbichette!
cs_pseudo3 Messages postés 268 Date d'inscription mardi 24 juillet 2007 Statut Membre Dernière intervention 2 février 2021 1
13 août 2012 à 10:49
Comme des tests effectués avec xBR sur le tableau de Mona Lisa ont révélé un rendu des craquelures meilleur qu'avec les autres méthode je note 10/10
cs_pseudo3 Messages postés 268 Date d'inscription mardi 24 juillet 2007 Statut Membre Dernière intervention 2 février 2021 1
13 août 2012 à 10:42
Bonjour,

A propos de "Dans mon code, il ne gère que les facteurs 2, 3 et 4" :

Voici un bout de code qui pallie à cet inconvénient si l'on souhaite effectuer un changement d'échelle avec un facteur différent du type réel comme 2,251 par exemple : c'est juste une ruse qui opère en deux deux temps :
1) agrandissement avec xbr4x,
2) correction d'échelle du résultat de xbr4x avec StretchBlt(mode HalfTone).

//==============================================================================
// XKR XKR XKR XKR XKR XKR XKR XKR XKR XKR XKR XKR XKR XKR XKR XKR XKR XKR XKR
//==============================================================================

procedure xbrKRx(const bm_in: TBitmap; const bm_out: TBitmap; KR: single);
var KR2: single; WR, HR: integer; pt: TPoint; bm_t: tBitMap;
begin
bm_T := tBitMap.create;
with bm_T do begin
width := 4 * bm_in.Width; height := 4 * bm_in.height; pixelFormat := pf32bit;
end;
xbr4x(bm_in, bm_T);
if KR = 4.0 then EXIT;

WR := trunc(bm_in.width * KR); HR := trunc(bm_in.height * KR);
bm_out.width:=WR; bm_out.height:=HR;

if GetStretchBltMode(bm_out.Canvas.Handle) <> HalfTone then
begin GetBrushOrgEx(bm_out.Canvas.Handle, pt);
SetStretchBltMode(bm_out.Canvas.Handle, HalfTone);
SetBrushOrgEx(bm_out.Canvas.Handle, pt.x, pt.y, @pt);
end;

StretchBlt(bm_out.Canvas.Handle, 0, 0, bm_out.Width, bm_out.Height,
bm_T.Canvas.Handle, 0, 0, bm_T.Width, bm_T.Height, SRCCOPY);
bm_T.free;
end;

procedure TFrmDemoMain.bXBRClick(Sender: TObject);
var kEntier : integer;
begin LabMis.caption := ''; LabMis.Update;
GTC := GetTickCount;

if ScaleValue=0.0 then Exit else
if ScaleValue=1.0 then imgResized.Picture.Bitmap.Assign(imgOriginal.Picture.Bitmap) else
if ScaleValue=2.0 then xbr2x(imgOriginal.Picture.Bitmap,imgResized.Picture.Bitmap) else
if ScaleValue=3.0 then xbr3x(imgOriginal.Picture.Bitmap,imgResized.Picture.Bitmap) else
if ScaleValue=4.0 then xbr4x(imgOriginal.Picture.Bitmap,imgResized.Picture.Bitmap)
else xbrKRx(imgOriginal.Picture.Bitmap, imgResized.Picture.Bitmap, ScaleValue);

LabMis.caption := 'xBR Mis : ' + intToStr(GetTickCount - GTC) + ' ms';
imgResized.Invalidate;
end;

A+.
cs_pseudo3 Messages postés 268 Date d'inscription mardi 24 juillet 2007 Statut Membre Dernière intervention 2 février 2021 1
12 août 2012 à 14:35
Re-Bonjour,

Oups je n'avais pas remarqué que la réponse du 12/08/2012 12:55:23 était de Caribensila dans ma précipitation je l'avais prise pour une troisième solution provenant de Barbichette : mille excuses Caribensila.

Barbichette : "d'ailleurs, il y a une faute due à la rapidité..." : Exact, je m'en suis rendu compte car les bitMaps me sortaient en dominante Bleue.
Mais ta deuxième solution R:= TRGBQuad(c0).rgbBLUE; G:= TRGBQuad(c0).rgbGreen; B:= TRGBQuad(c0).rgbRED; A:= TRGBQuad(c0).rgbReserved; où le rouge et le bleu sont inversés marche correctement.

A+.
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
12 août 2012 à 13:15
d'ailleur, il y a une faute due à la rapidité...
R=(color and $FF) shr 0;
G=(color and $FF00) shr 8;
B=(color and $FF0000) shr 16;
A=(color and $FF000000) shr 24;

ou

R=(color shr 0) and $FF;
G=(color shr 8) and $FF;
B=(color shr 16) and $FF;
A=(color shr 24) and $FF;
cs_pseudo3 Messages postés 268 Date d'inscription mardi 24 juillet 2007 Statut Membre Dernière intervention 2 février 2021 1
12 août 2012 à 13:11
Re-bonjour,

Mille fois merci Barbichette pour la réponse et la rapidité.
C'est fou le nombre de solutions existantes.
Entre-temps j'ai constaté qu'avec GetRValue(), GetGValue() et GetBValue() on s'en sort aussi mais le GetRGBReservedValue() n'existe pas.

En tous cas merci avec le A=(color and $FF) shr 24 ce sera mieux.

Bon dimanche, et A+.
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
12 août 2012 à 12:55
... ou alors :

type
TColorRec = record
case integer of
0 : ( Color : TColor );
1 : ( R,G,B,A : Byte );
end;
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
12 août 2012 à 12:37
En général on parle de RGBA (pour la couche Alpha), ce qui correspond au tbitmap.pixelformat=pf32bit
R=(color and $FF) shr 0;
G=(color and $FF) shr 8;
B=(color and $FF) shr 16;
A=(color and $FF) shr 24;

color=R+G shl 8+B shl 16+A shl 24;

autre solution :
TRGBQuad(color).rgbBlue;
TRGBQuad(color).rgbGreen;
TRGBQuad(color).rgbRed;
TRGBQuad(color).rgbReserved;
Par contre, dans ce cas, il me semble que le rouge et le bleu sont inversés.

voili, voilou...
cs_pseudo3 Messages postés 268 Date d'inscription mardi 24 juillet 2007 Statut Membre Dernière intervention 2 février 2021 1
12 août 2012 à 12:24
Bonjour,

Juste une petite question et sa réciproque :
Comment extraire les composantes R,G,B et RGBReserved d'une couleur déclarée en type longint,
et comment à partir de nouvelles composantes R,G,B et RGBReserved créer sa cousine du type longint ?

Merci par avance.

A+.
cs_pseudo3 Messages postés 268 Date d'inscription mardi 24 juillet 2007 Statut Membre Dernière intervention 2 février 2021 1
11 août 2012 à 14:51
Re-bonjour;

OK, merci pour la fonction.

Entre-temps j'ai transféré UAdaptiveResize dans l'appli de Cirec pour comparer les résultats des xBR à ceux de BiCubicScale, StretchBmpAlpha3 et de StretchBlt(HalfTone) : les différences de rendu visuel sont assez faibles (sauf si on utilise StretchBlt sans HalfTone).
Choisir entre les 4 méthodes est assez difficile d'autant plus qu'en matière de rendu visuel chacun a ses préférences de goût.

Par contre pour ce qui est des vitesses xBR s'en sort pas mal, voici des résultats pour un agrandissement de 400% d'un bitmap-source de 683x1024 :
1 - StretchBlt : mis 109 ms,
2 - xBR : mis 344 ms,
3 - StretchBmpAlpha3 : mis 593 ms,
4 - BiCubicScale : mis 5866 ms.

Reste que si on veut un changement d'échelle avec un ScaleFactor différent de 2, 3 et 4, comme par exemple 3.55, le choix entre les 4 méthodes se simplifie un peu.
L'algo du xBR n'est-il pas adaptable aux ScaleFactor's de valeur réelle ? (Avec un bidouillage basé sur des règles de trois par exemple ?).

A+.
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
11 août 2012 à 13:59
oui, c'est ça, sinon ajoute la fonction :
function ifthen(condition:boolean;OK:integer;NOK:integer):integer;
begin
if condition then result:=OK else result:=NOK;
end;
cs_pseudo3 Messages postés 268 Date d'inscription mardi 24 juillet 2007 Statut Membre Dernière intervention 2 février 2021 1
11 août 2012 à 13:44
Bonjour,

Impatient de comparer, j'ai voulu tester ton code, mais mon compilo me dit [Erreur fatale] UAdaptiveResize.pas(5): Fichier non trouvé : 'StrUtils.dcu'
et s'arrête ensuite sur un ifthen que Delphi-5 ignore.

Je suppose que les lignes du type "px :=ifthen((df(PE,PF) <= df(PE,PH)),PF,PH);"
doivent être remplacées par if df(PE,PF) <= df(PE,PH) then px:=PF else px = PH) : Oui/Non ?

A+.
Rejoignez-nous