Rotation avec interpolation

Partagez votre expérience de PureBasic avec les autres utilisateurs.
comtois
Messages : 5172
Inscription : mer. 21/janv./2004 17:48
Contact :

Rotation avec interpolation

Message par comtois »

Pour éviter les trous dans l'image finale, il faut parcourir tous les pixels de l'image finale et chercher, pour chacun d'eux, l'antécédent dans l'image initiale, c'est à dire obtenu par rotation inverse.

Rotation avec interpolation au plus proche voisin (ordre 0), c'est la méthode la plus simple. Je n'ai pas cherché à optimiser.
L'interpolation bilinéaire est d'ordre 1, dès que je trouve un peu de temps et de motivation j'ajouterai un code.

Code : Tout sélectionner

Structure Pixel
  r.l
  g.l
  b.l
EndStructure

Dim Image.Pixel(254,254)


If OpenWindow(0, 100, 100, 600, 300, "PureBasic - Image")
  
  If CreateImage(0, 255, 255)
    
    StartDrawing(ImageOutput(0))
    
    For k=0 To 255
      FrontColor(RGB(k,0, k))  ; a rainbow, from black to pink
      Line(0, k, 255, 1)
    Next
    
    DrawingMode(#PB_2DDrawing_Transparent)
    FrontColor(RGB(255,255,255)) ; print the text to white !
    DrawText(40, 50, "An image easily created !")
    
    For y=0 To 254
      For x=0 To 254
        Image(x,y)\r = Red(Point(x,y))
        Image(x,y)\g = Green(Point(x,y))
        Image(x,y)\b = Blue(Point(x,y))
      Next
    Next  
    StopDrawing() ; This is absolutely needed when the drawing operations are finished !!! Never forget it !
    
  EndIf
  
  w=255
  h=255
  angle=30
  Cos.f=Cos(Radian(angle))
  Sin.f=Sin(Radian(angle))
  
  If CreateImage(1, 255, 255)
    
    StartDrawing(ImageOutput(1))
    
    For y2=0 To 254
      For x2=0 To 254
        x1.f = w/2 +cos*(x2-w/2)-sin*(y2-h/2)
        y1.f = h/2 +sin*(x2-w/2)+cos*(y2-h/2)
        x = x1 + 0.5
        y = y1 + 0.5
        If x>=0 And x<255 And y>=0 And y<255
          Plot(x2,y2, RGB(Image(x,y)\r,Image(x,y)\g, Image(x,y)\b))
        EndIf  
      Next
    Next 
    
    StopDrawing()
  EndIf
    
  Repeat
    Event = WaitWindowEvent()
    
    If Event = #PB_Event_Repaint
      StartDrawing(WindowOutput(0))
      DrawImage(ImageID(0), 20, 10)
      DrawImage(ImageID(1), 40+255, 10)
      StopDrawing()    
    EndIf
    
  Until Event = #PB_Event_CloseWindow  ; If the user has pressed on the close button
  
EndIf

End   ; All the opened windows are closed automatically by PureBasic
Dernière modification par comtois le sam. 01/nov./2014 19:44, modifié 2 fois.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
comtois
Messages : 5172
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: Rotation avec interpolation

Message par comtois »

Version avec interpolation bilinéaire, je n'ai pas traité les bords de l'image et ce n'est pas optimisé, c'est juste pour montrer le principe.
Selon Wikipedia :
This algorithm reduces some of the visual distortion caused by resizing an image to a non-integral zoom factor, as opposed to nearest neighbor interpolation, which will make some pixels appear larger than others in the resized image. Bilinear interpolation tends, however, to produce a greater number of interpolation artifacts (such as aliasing, blurring, and edge halos) than more computationally demanding techniques such as bicubic interpolation
Autrement dit la prochaine étape devrait être l'interpolation bicubique.

Code : Tout sélectionner

;
; ------------------------------------------------------------
;
;   PureBasic - Image example file
;
;    (c) Fantaisie Software
;
; ------------------------------------------------------------
;
Structure Pixel
  r.l
  g.l
  b.l
EndStructure

Dim Image.Pixel(254,254)


If OpenWindow(0, 100, 100, 600, 300, "PureBasic - Image")
  
  If CreateImage(0, 255, 255)
    
    StartDrawing(ImageOutput(0))
    
    For k=0 To 255
      FrontColor(RGB(k,0, k))  ; a rainbow, from black to pink
      Line(0, k, 255, 1)
    Next
    Box(30, 40, 200, 40, RGB(55, 55, 120))
    Circle(127, 127, 25, RGB(255, 255, 0))
    LineXY(0, 127, 254, 127, RGB(0, 255, 0))
    LineXY(127, 0, 127, 254, RGB(0, 255, 255))
    LineXY(0, 0, 254, 254, RGB(255, 0, 0))
    Circle(127, 13, 10, RGB(55, 255, 0))
    DrawingMode(#PB_2DDrawing_Transparent)
    FrontColor(RGB(255,255,255)) ; print the text to white !
    DrawText(40, 50, "An image easily created !")
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(0,0,255,255, RGB(255,255,255))
    For y=0 To 254
      For x=0 To 254
        Image(x,y)\r = Red(Point(x,y))
        Image(x,y)\g = Green(Point(x,y))
        Image(x,y)\b = Blue(Point(x,y))
      Next
    Next  
    StopDrawing() ; This is absolutely needed when the drawing operations are finished !!! Never forget it !
    
  EndIf
  
  w.d=255
  h.d=255
  w2.d=w/2.0
  h2.d=h/2.0
  angle=45
  Cos.d=Cos(Radian(angle))
  Sin.d=Sin(Radian(angle))
  
  If CreateImage(1, 255, 255)
    
    StartDrawing(ImageOutput(1))
    
    For y2=0 To 254
      For x2=0 To 254
        x1.d = w2 +cos*(x2-w2)-sin*(y2-h2)
        y1.d = h2 +sin*(x2-w2)+cos*(y2-h2)
        x = x1 ;+ 0.5
        y = y1 ;+ 0.5
        x0=Int(x1)
        y0=Int(y1)
        Ex.d = x1-x0 
        Ey.d = y1-y0 
        
        If x0>=0 And x0<=254 And y0>=0 And y0<=254 
          If x0=254 : x0=253 : EndIf
          If y0=254 : y0=253 : EndIf
          r = (1-Ex)*(1-Ey)*Image(x0,y0)\r+(1-Ex)*Ey*Image(x0,y0+1)\r+Ex*(1-Ey)*Image(x0+1,y0)\r+Ex*Ey*Image(x0+1,y0+1)\r
          g = (1-Ex)*(1-Ey)*Image(x0,y0)\g+(1-Ex)*Ey*Image(x0,y0+1)\g+Ex*(1-Ey)*Image(x0+1,y0)\g+Ex*Ey*Image(x0+1,y0+1)\g
          b = (1-Ex)*(1-Ey)*Image(x0,y0)\b+(1-Ex)*Ey*Image(x0,y0+1)\b+Ex*(1-Ey)*Image(x0+1,y0)\b+Ex*Ey*Image(x0+1,y0+1)\b
          Plot(x2,y2, RGB(r, g, b))
        EndIf  
      Next
    Next 
    
    StopDrawing()
  EndIf
  
  
  
  Repeat
    Event = WaitWindowEvent()
    
    If Event = #PB_Event_Repaint
      StartDrawing(WindowOutput(0))
      DrawImage(ImageID(0), 20, 10)
      DrawImage(ImageID(1), 40+255, 10)
      StopDrawing()    
    EndIf
    
  Until Event = #PB_Event_CloseWindow  ; If the user has pressed on the close button
  
EndIf

End   ; All the opened windows are closed automatically by PureBasic
Dernière modification par comtois le sam. 01/nov./2014 19:39, modifié 1 fois.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Lord Nelson
Messages : 355
Inscription : dim. 01/déc./2013 15:29

Re: Rotation avec interpolation

Message par Lord Nelson »

Chapeau 8)
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Rotation avec interpolation

Message par Kwai chang caine »

Merci Comtois 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Mesa
Messages : 1097
Inscription : mer. 14/sept./2011 16:59

Re: Rotation avec interpolation

Message par Mesa »

J'ai trouvé un algorithme pour le bicubic qui semble valable ici :
http://www.tinaja.com/glib/pixintpl.pdf

Je l'ai trouvé en fouillant ici http://www.xtremevbtalk.com/archive/ind ... 19913.html


Mesa.
Mesa
Messages : 1097
Inscription : mer. 14/sept./2011 16:59

Re: Rotation avec interpolation

Message par Mesa »

J'ai commencé à coder mais je n'ai pas le temps de finir pour l'instant :oops: . Si quelqu'un veut finir, il n'y a plus qu'à "remplir" :wink: sinon, j'essaierais de le finir un de ces jours.

Code : Tout sélectionner

Structure Pixel
  r.l
  g.l
  b.l
EndStructure

Procedure CreateImage24(id, wii, hii)
  
  If CreateImage(id, wii, hii)
    
    StartDrawing(ImageOutput(id))
    
    For k=0 To wii
      FrontColor(RGB(k,0, k))  ; a rainbow, from black to pink
      Line(0, k, wii, 1)
    Next
    
    DrawingMode(#PB_2DDrawing_Transparent)
    FrontColor(RGB(255,255,255)) ; print the text to white !
    DrawText(40, 50, "An image easily created !")
    
    StopDrawing() ; This is absolutely needed when the drawing operations are finished !!! Never forget it !
    
  EndIf 
  ImageGadget(0, 20, 10, wi, hi, ImageID(id))
EndProcedure

Procedure RotationBiliaire(id)
  wi=ImageWidth(id)
  hi=ImageHeight(id)
  
  Dim Image.Pixel(wi,hi)
  
  StartDrawing(ImageOutput(id))
  For y=0 To hi-1
    For x=0 To wi-1
      Image(x,y)\r = Red(Point(x,y))
      Image(x,y)\g = Green(Point(x,y))
      Image(x,y)\b = Blue(Point(x,y))
    Next
  Next  
  StopDrawing() 
  
  w.d=wi
  h.d=hi
  w2.d=w/2.0
  h2.d=h/2.0
  angle=30
  Cos.d=Cos(Radian(angle))
  Sin.d=Sin(Radian(angle))
  
  If CreateImage(id+1, wi, hi)
    
    StartDrawing(ImageOutput(id+1))
    
    For y2=0 To hi-1
      For x2=0 To wi-1
        x1.d = w2 +cos*(x2-w2)-sin*(y2-h2)
        y1.d = h2 +sin*(x2-w2)+cos*(y2-h2)
        x0=Int(x1)
        y0=Int(y1)
        Ex.d = x1-x0
        Ey.d = y1-y0
        ;f(x,y) = f(0,0)(1-x)(1-y) + f(1,0)(x)(1-y) +
        ;f(0,1)(1-x)(y) + f(1,1)(x)(y)
        ;f(0,0)=Image(x0,y0)\rgb
        ;f(1,0)=Image(x0+1,y0)\rgb
        ;f(0,1)=Image(x0,y0+1)\rgb
        ;f(1,1)=Image(x0+1,y0+1)\rgb
        If x0>0 And x0<wi-1 And y0>0 And y0<hi-1
          r = (1-Ex)*(1-Ey)*Image(x0,y0)\r+(1-Ex)*Ey*Image(x0,y0+1)\r+Ex*(1-Ey)*Image(x0+1,y0)\r+Ex*Ey*Image(x0+1,y0+1)\r
          g = (1-Ex)*(1-Ey)*Image(x0,y0)\g+(1-Ex)*Ey*Image(x0,y0+1)\g+Ex*(1-Ey)*Image(x0+1,y0)\g+Ex*Ey*Image(x0+1,y0+1)\g
          b = (1-Ex)*(1-Ey)*Image(x0,y0)\b+(1-Ex)*Ey*Image(x0,y0+1)\b+Ex*(1-Ey)*Image(x0+1,y0)\b+Ex*Ey*Image(x0+1,y0+1)\b
          Plot(x2,y2, RGB(r, g, b))
        EndIf  
      Next
    Next 
    
    StopDrawing()
  EndIf
  ImageGadget(1, 20+wi, 10, wi, hi, ImageID(id+1))
EndProcedure

Procedure RotationBicubic(id)
  wi=ImageWidth(id)
  hi=ImageHeight(id)
  a00.Pixel
  a01.Pixel
  a02.Pixel
  a03.Pixel
  a10.Pixel
  a11.Pixel
  a12.Pixel
  a13.Pixel
  a20.Pixel
  a21.Pixel
  a22.Pixel
  a23.Pixel
  a30.Pixel
  a31.Pixel
  a32.Pixel
  a33.Pixel
  ;...
  
  Dim Image.Pixel(wi,hi)
  
  StartDrawing(ImageOutput(id))
  For y=0 To hi-1
    For x=0 To wi-1
      Image(x,y)\r = Red(Point(x,y))
      Image(x,y)\g = Green(Point(x,y))
      Image(x,y)\b = Blue(Point(x,y))
    Next
  Next  
  StopDrawing() 
  
  w.d=wi
  h.d=hi
  w2.d=w/2.0
  h2.d=h/2.0
  angle=30
  Cos.d=Cos(Radian(angle))
  Sin.d=Sin(Radian(angle))
  
  If CreateImage(id+1, wi, hi)
    
    StartDrawing(ImageOutput(id+1))
    
    For yf=0 To hi-1
      For xf=0 To wi-1
        x1.d = w2 +cos*(xf-w2)-sin*(yf-h2)
        y1.d = h2 +sin*(xf-w2)+cos*(yf-h2)
        x0=Int(x1)
        y0=Int(y1)
        Ex.d = x1-x0
        Ey.d = y1-y0
        
        ;f(0,0)=Image(x0,y0)\rgb
        ;f(1,0)=Image(x0+1,y0)\rgb
        ;f(0,1)=Image(x0,y0+1)\rgb
        ;f(1,1)=Image(x0+1,y0+1)\rgb
        
        ;================			
        ;/// A FINIR  \\\  
        ;================	  
        
        ;=============================================		  
        ;Voir http://www.tinaja.com/glib/pixintpl.pdf  
        ;=============================================					
        
        ;f(0,0)=Image(x0,y0)\rgb
        ;f(1,0)=Image(x0+1,y0)\rgb
        ;f(0,1)=Image(x0,y0+1)\rgb
        ;f(1,1)=Image(x0+1,y0+1)\rgb
        
        w0.pixel
        ; 	  w0\r=Image(x0,y0)\r
        ; 	  w0\g=Image(x0,y0)\g
        ; 	  w0\b=Image(x0,y0)\b
        
        ;prepa des coef
        ; w0 = f(0,0) = a00
        ; w1 = f(1,0) = a00 + a10 + a20 + a30
        ; w2 = f(0,1) = a00 + a01 + a02 + a03
        ; w3 = f(1,1) = a00 + a10 + a20 + a30 +
        ;               a01 + a11 + a21 + a31 +
        ;               a02 + a12 + a22 + a32 +
        ;               a03 + a13 + a23 + a33
        ;pente en x (devrait être a dérivée partielle mais ici la moyenne des variations
        ; x0 = fx(0,0) = a10
        ; x1 = fx(1,0) = a10 + 2a20 + 3a30
        ; x2 = fx(0,1) = a10 + a11 + a12 + a13
        ; x3 = fx(1,1) = 1*(a10 + a11 + a12 + a13) +
        ;                2*(a20 + a21 + a22 + a23) +
        ;                3*(a30 + a31 + a32 + a33)
        ;pente en y (devrait être a dérivée partielle mais ici la moyenne des variations  
        ; y0 = fy(0,0) = a01
        ; y1 = fy(1,0) = a01 + a11 + a21 + a31
        ; y2 = fy(0,1) = a01 +2Aa02 + 3a03
        ; y3 = fy(1,1) = 1*(a01+a11+a21+a31) +
        ;                2*(a02+a12+a22+a32) +
        ;                3*(a03+a13+a23+a33)
        ;pente en "xy" 
        ; z0 = fxy(0,0) = a11
        ; z1 = fxy(1,0) = a11 + 2a21 + 3a31
        ; z2 = fxy(0,1) = a11 + 2a12 + 3a13
        ; z3 = fxy(1,1) = 1*a11 + 2*a12 + 3*a13 +
        ;                 2*a21 + 4*a22 + 6*a23 +
        ;                 3*a31 + 6*a32 + 9*a33
        ; coeff
        ; a00 = w0,
        ; a01 = y0,
        ; a02 = -3w0 + 3w2 -2y0 - y2
        ; a03 = 2w0 - 2w2 + y0 + y2
        ; a10 = x0
        ; a11 = z0
        ; a12 = -3x0 + 3x2 - 2z0 - z2
        ; a13 = 2x0 - 2x2 + z0 + z2
        ; a20 = -3w0 + 3w1 - 2x0 - x1
        ; a21 = -3y0 + 3y1 - 2z0 - z1
        ; a22 = 9w0 - 9w1 - 9w2 + 9w3 + 6x0 + 3x1 +
        ; -6x2 - 3x3 + 6y0 - 6y1 + 3y2 - 3y3 +
        ; 4z0 + 2z1 + 2z2 + z3
        ; a23 = -6w0 + 6w1 + 6w2 - 6w3 -4x0 - 2x1 +
        ; 4x2 + 2x3 -3y0 + 3y1 - 3y2 + 3y3 +
        ; -2z0 - z1 - 2z2 - z3
        ; a30 = 2w0 - 2w1 + x0 + x1
        ; a31 = 2y0 - 2y1 + z0 + z1
        ; a32 = -6w0 + 6w1 + 6w2 -6 w3 -3x0 - 3x1 +
        ;        3x2 + 3x3 -4y0 + 4y1 - 2y2 + 2y3 +
        ;        -2z0 - 2z1 - z2 - z3
        ; a33 = 4w0 - 4w1 - 4w2 + 4w3 + 2x0 + 2x1 +
        ;       -2x2 - 2x3 + 2y0 - 2y1 + 2y2 - 2y3 +
        ;       z0 + z1 + z2 + z3
        
        ; finalement	  
        ; p(x,y) = a00*x^0^y^0 + a01*x^0^y^1 +
        ; a02*x^0^y^2 + a03*x^0^y^3 +
        ; a10*x^1^y^0 + a11*x^1^y^1 +
        ; a12*x^1^y^2 + a13*x^1^y^3 +
        ; a20*x^2^y^0 + a21*x^2^y^1 +
        ; a22*x^3^y^2 + a23*x^2^y^3 +
        ; a30*x^3^y^0 + a31*x^3^y^1 +
        ; a32*x^3^y^2 + a33*x^3^y^3
        If x0>0 And x0<wi-1 And y0>0 And y0<hi-1
          ;x^0 = y^0 = 1 and x^1= x And y^1= y
;           r = a00\r + a01\r*1^y + a02\r*1^y^2 + a03\r*1^y^3 + a10*x^1^y^0 + a11*x^1^y^1 +
;           g = 
;           b = 
          Plot(xf,yf, RGB(r, g, b))
        EndIf  
      Next
    Next 
    
    StopDrawing()
  EndIf
  ImageGadget(1, 20+wi, 10, wi, hi, ImageID(id+1)) 	 
  
EndProcedure

id=0
wi=255
hi=255

If OpenWindow(0, 100, 100, 600, 300, "PureBasic - Image")
  ImageGadget(0, 20, 10, wi, hi,0)
  ImageGadget(1, 20+wi, 10, wi, hi,0)
  
  CreateImage24(id, wi, hi)
  RotationBiliaire(id)
  ;RotationBicubic(id)
  
  
  
  Repeat
    Event = WaitWindowEvent()
    
    
    
  Until Event = #PB_Event_CloseWindow  ; If the user has pressed on the close button
  
EndIf

End   ; All the opened windows are closed automatically by PureBasic


;http://www.xtremevbtalk.com/archive/index.php/t-319913.html
;http://www.tinaja.com/glib/pixintpl.pdf
; Bicubic Interpolation
; This is the Godzilla of pixel interpolation algorithms. It gives absolutely superb
; results With negligible artifacts. But is very hard To understand And requires an
; extreme number of complex calculations.
; Bicubic Interpolation attempts To reconstruct the exact surface between your four
; initial pixels. It does this by extracting sixteen pieces of information. Based on the
; values of the samples, the x slopes of those values, the y slopes of those values,
; And the xy slope cross products of those values.
; It turns out that any point on a two dimensional unity normalized surface can be
; represented by a set of sixteen cubic polynomial equations.
; The key bicubic equations are…
; p(x,y) = a00*x^0^y^0 + a01*x^0^y^1 +
; a02*x^0^y^2 + a03*x^0^y^3 +
; a10*x^1^y^0 + a11*x^1^y^1 +
; a12*x^1^y^2 + a13*x^1^y^3 +
; a20*x^2^y^0 + a21*x^2^y^1 +
; a22*x^3^y^2 + a23*x^2^y^3 +
; a30*x^3^y^0 + a31*x^3^y^1 +
; a32*x^3^y^2 + a33*x^3^y^3
; This expression can be simplified somewhat by noting that x^0 = y^0 = 1 And x^1
; = x And y^1= y. Our non-trivial problem is To find the sixteen constant coefficients
; a00 through a33 For an initial four unit square Data points And their nearest eight
; neighbors.
; We can start by substituting some variables To simplify the notation. So, let w0 =
; f(0,0) Or the pixel value at our lower left point. Let w1 = (f0,1) Or the pixel value
; at our lower right point. Let w2 = f(0,0) Or the pixel value at our upper left point.
; And let w3 = (f1,1) Or the pixel value at our upper right point.
; Similarly, we will let x0 through x3 represent the xslope (Or partial derivative With
; respect To x) at each point. Normally, we do Not know the exact x slope value.
; So, we can approximate it by taking the average of the changes between your
; previous And Next Data point.
; We can also let y0 through y3 represent the yslope (Or partial derivative With
; respect To y) at each point. Finally, To handle the behavior near the middle of our
; four Data point set, we can let z0 through z3 represent the slope product Or
; (partial derivative cross product) at each point.
; —83.6—
; We actually End up using 16 Data points For calculation, With the "extras" being
; needed To find our x And y slopes. This is Not a problem interior To your pixel
; Map. But you will have To do something at the edges To either ignore Or fake the
; slopes. Which is why our sample Data has "extra" values around its outside edge.
; The results can be quite impressive…
; We see an artifact free surface that we can pick any point off of. The surface is
; continuous And has continuous slopes at every point.
; Bicubic calculations are often done using matrix techniques. Since these can be
; hard To understand, we will instead use ordinary algebra here. Helped along With
; a partial differential equation Or two. All you will need To know about partial
; differentials here is that (A) A partial differential is the slope in one variable
; direction, And (B) The differential ( Or its limit derivative ) of f(x) = b0 + b1x +
; b2x^2 + b3x^3 is its slope of b1 + 2b2x + 3b3x^2.
; Finding a new bicubic interpolated pixel value inside a unit square starts off by
; finding w0 through z3. These are already known from our available pixel Data, Or
; can be easily calculated from it. You then use these w0 through z3 To evaluate
; expressions For the various ax coefficients.
; Sadly, we now have w0 through z3 As a function of a00 through a33. We instead
; need a00 through a33 As a function of w0 through z3. So, we have To solve 16
; linear equations in 16 unknowns To isolate the axx values.
; —83.7—
; Finally, from our newly calculated a00 through a33 values, we can find the value
; of our new pixel using our bicubic formula shown above.
; Here is how w0 through z3 are related To the a00 through a33 coefficients…
; w0 = f(0,0) = a00
; w1 = f(1,0) = a00 + a10 + a20 + a30
; w2 = f(0,1) = a00 + a01 + a02 + a03
; w3 = f(1,1) = a00 + a10 + a20 + a30 +
; a01 + a11 + a21 + a31 +
; a02 + a12 + a22 + a32 +
; a03 + a13 + a23 + a33
; x0 = fx(0,0) = a10
; x1 = fx(1,0) = a10 + 2a20 + 3a30
; x2 = fx(0,1) = a10 + a11 + a12 + a13
; x3 = fx(1,1) = 1*(a10 + a11 + a12 + a13) +
; 2*(a20 + a21 + a22 + a23) +
; 3*(a30 + a31 + a32 + a33)
; y0 = fy(0,0) = a01
; y1 = fy(1,0) = a01 + a11 + a21 + a31
; y2 = fy(0,1) = a01 +2Aa02 + 3a03
; y3 = fy(1,1) = 1*(a01+a11+a21+a31) +
; 2*(a02+a12+a22+a32) +
; 3*(a03+a13+a23+a33)
; z0 = fxy(0,0) = a11
; z1 = fxy(1,0) = a11 + 2a21 + 3a31
; z2 = fxy(0,1) = a11 + 2a12 + 3a13
; z3 = fxy(1,1) = 1*a11 + 2*a12 + 3*a13 +
; 2*a21 + 4*a22 + 6*a23 +
; 3*a31 + 6*a32 + 9*a33
; In general, these equations are found by substituting 1 And 0 values For x And y
; And their slope derivatives. Let’s look at four typical examples…
; • w2: Finds value at x=0, y=1. x=0 drops out all
; equations With powers of x=1, x=2, And x=3.
; Leaving a01*y + a02*y + a03*y. Which at y=1
; becomes w2 = a01 + a02 + a03.
; • x1: Finds xslope at x=1, y=0. y=0 drops out all
; equations With powers of y=1, y=2, And y=3.
; Leaving a10*x + a20*x^2 + a30*x^3. Whose
; partial derivative is a10 + 2a20*x + 3a30*x^2.
; —83.8—
; • y3: All equations are initially active. x=1
; everywhere. y slopes will be 0 + a01y + ... +
; a02y + ... + 3a03y^2 + ... Which at y=1 will
; become the result shown.
; • z3: Cross products of the slopes
; will be a11(1x*1y) + a12(1x*2y) + a13(1x*3y^2)
; + a21(2x^2*y) + a22(2x^2*2y^2) + ... Which
; at x=1 And y=1 becomes 1a11 + 2a12 + 3a13 +
; 2a21 + 4a22 + ...
; Finding the Coefficients
; We do now have w0 through z3 As functions of a00 through a33. To solve For
; individual axx values, we have To solve 16 linear equations in 16 unknowns. This
; can be done manually, Or by inserting the values into any of several math
; equation programs. The results should be…
; a00 = w0,
; a01 = y0,
; a02 = -3w0 + 3w2 -2y0 - y2
; a03 = 2w0 - 2w2 + y0 + y2
; a10 = x0
; a11 = z0
; a12 = -3x0 + 3x2 - 2z0 - z2
; a13 = 2x0 - 2x2 + z0 + z2
; a20 = -3w0 + 3w1 - 2x0 - x1
; a21 = -3y0 + 3y1 - 2z0 - z1
; a22 = 9w0 - 9w1 - 9w2 + 9w3 + 6x0 + 3x1 +
; -6x2 - 3x3 + 6y0 - 6y1 + 3y2 - 3y3 +
; 4z0 + 2z1 + 2z2 + z3
; a23 = -6w0 + 6w1 + 6w2 - 6w3 -4x0 - 2x1 +
; 4x2 + 2x3 -3y0 + 3y1 - 3y2 + 3y3 +
; -2z0 - z1 - 2z2 - z3
; a30 = 2w0 - 2w1 + x0 + x1
; a31 = 2y0 - 2y1 + z0 + z1
; a32 = -6w0 + 6w1 + 6w2 -6 w3 -3x0 - 3x1 +
; 3x2 + 3x3 -4y0 + 4y1 - 2y2 + 2y3 +
; -2z0 - 2z1 - z2 - z3
; a33 = 4w0 - 4w1 - 4w2 + 4w3 + 2x0 + 2x1 +
; -2x2 - 2x3 + 2y0 - 2y1 + 2y2 - 2y3 +
; z0 + z1 + z2 + z3
; —83.9—
; It is tedious And highly error prone To try And do this by hand. There are some
; obvious simplifications. Four values are available by inspection. Eight of these can
; be solved With pairs of equations. Leaving four equations in four unknowns.
; Ferinstance, If you want To do a manual solution, you can grab a00, a01, a10, And
; a11 by inspection. w1 And x1 can then be simultaneously solved For a20 And a30.
; Then x2 And z2 can be simultaneously solved For a12 And a13. And w2 And y2
; can be simultaneously solved For a02 And a03. And y1 And z1 can in turn get
; simultaneously solved For a21 And a31.
; If you save them For last, the remaining variables can End up As four equations in
; four unknowns. With all previous calculated values being reducible down into four
; constants, one For each equation. Two of these equations can then relate a22 And
; a33, While another two can relate a32 And a33. And substituted back To solve For
; a33. The final three variables follow by simple arithmetic.
; A Summary
; An important warning: Bicubic calculations might rarely End up slightly above
; unity Or slightly below zero. The rest of your code must be able To clip these
; values Or otherwise deal With them.
; Again on one unoptimized And older PostScript implementation, the execution
; time per pixel For a bicubic interpolation was just over 100 microseconds. Thus
; bicubic speed in this instance is seven times worse than bilineal And is ten times
; worse than nearest neighbor.
; I suspect that when further optimized on a newer Distiller And a faster machine,
; the results will End up something like three seconds per megabyte per color
; plane For bilineal And twenty seconds per megabyte per color plane For bicubic.
; Thus, bicubic can most certainly be used For typical PostScript bitmap image
; manipulations but will likely ForEver remain somewhat on the slow side.
; Your results will vary With your language And implementation choices. Again,
; compiled languages will usually beat out interpreted ones. Hand crafted machine
; code will often be much faster still, And custom hardware may even be faster.
; Reducing bilineal To somewhat coarser table lookups may Or may Not prove time
; effective Or worthwhile on some implementations.
; In some cases, doubling your sample rate can significantly reduce interpolation
; problems. But only With 4X speed And 4x storage penalties that may Not End up
; being cost effective.
; I originally thought a 2X sampled 3x3 compromise interpolation solution would
; be useful For such things As eBay images . But it appears that a genuine bicubic
; interpolation can End up nearly speed competitive.
; With far better results.
; —83.10—
; Some Improvements
; Finding "real" derivative slopes at each Data point could possibly further improve
; bicubic. This would tend To sharpen the transitions. But would take some sort of
; more content specific And wider area processing.
Désolé :roll:
M.
Répondre