In [2]:
import numpy as np
from PIL import Image
The following is a function to convert a 2D array of 3D points in homogeneous points:ΒΆ
In [3]:
def h(p):
    """
    Transform vectors into homogeneous coordinates. Bidimentional arrays will be considered as collections of points, 
    where the columns are the sample dimention.
    """
    if len(p.shape) > 2:
        raise ValueError("Shape > 2")
    if len(p.shape) == 1:
        p = np.expand_dims(p, axis=1)
    if p.shape[0] < 2 or p.shape[0] > 3:
        raise ValueError("Inputs must be 2D or 3D vectors. Check row dimension.")
    num_samples = p.shape[1]
    return np.vstack([p, np.ones((1,num_samples))])

def test_h():
    p1 = np.array([1,2,3])
    p1h = h(p1)
    assert len(p1h) == 4
    assert p1h[3] == 1
    for i, v in enumerate(p1):
        assert v == p1h[i]
    p2 = np.array([[1,2,3]])
    try:
        print(h(p2))
    except ValueError as err:
        assert str(err) == "Inputs must be 2D or 3D vectors. Check row dimension."
    p3 = np.zeros((2,2,2))
    try:
        h(p3)
    except ValueError as err:
        assert str(err) == "Shape > 2"  
    p4 = np.empty((3,4))
    p4h = h(p4)
    assert p4h.shape[0] == 4
    assert np.all(p4h[3,:] == 1)
    for i, v in enumerate(p1):
        assert v == p1h[i,:]

test_h()
In [6]:
def bilinear_approximation(P, img):
    """
    Note: the input point cooridinate values must be all in the valid image dimensions range.
    """
    # check input shape
    if len(P.shape) > 2:
        raise ValueError("Input dimensions > 2. Input must be an array of floating point pixel coordinates.")
    if len(P.shape) == 1:
        P = np.expand_dims(P, axis=1)
    if P.shape[0] != 2:
        raise ValueError("Inputs must be 2D pixel cooridinates. Check row dimentions.")
    if isinstance(img, Image.Image):
        img = np.asarray(img)
    # find the corner values of the input pixels
    w,h = img.shape
    Px_up = np.ceil(P[0,:]).astype(int)
    Px_dn = np.floor(P[0,:]).astype(int)
    Py_up = np.ceil(P[1,:]).astype(int)
    Py_dn = np.floor(P[1,:]).astype(int)
    Pbr = np.vstack([Px_up, Py_up])
    Pbl = np.vstack([Px_dn, Py_up])
    Ptr = np.vstack([Px_up, Py_dn])
    Ptl = np.vstack([Px_dn, Py_dn])
#     print("tr:\n", Ptr)
#     print("tl:\n", Ptl)
#     print("lr:\n", Pbr)
#     print("ll:\n", Pbl)
    # use this cooridinates to compute the bilinear approximaton of the original pixel
    bx = (img[Pbr[0,:], Pbr[1,:]] + 
           img[Pbl[0,:], Pbl[1,:]] + 
           img[Ptr[0,:], Ptr[1,:]] + 
           img[Ptl[0,:], Ptl[1,:]])/4
    return bx

def test_bl():
    P = np.array([
        [0, 2.4, 4],
        [0, 1.3, 4]
    ])
    img = np.arange(5*5, dtype=float).reshape(5,5)
    bx = bilinear_approximation(P, img)
#     print('Points: \n', P)
#     print('img = \n', img)
#     print('bx = ', bx)
    assert bx[0] == 0
    assert bx[1] == 14
    assert bx[2] == 24
    im = Image.fromarray(np.uint8(img))
    bx = bilinear_approximation(P, im)
    assert bx[0] == 0
    assert bx[1] == 14
    assert bx[2] == 24
    
    
test_bl()
> <ipython-input-6-53506ffaa168>(17)bilinear_approximation()
     15     # find the corner values of the input pixels
     16     pdb.set_trace()
---> 17     w,h = img.shape
     18     Px_up = np.ceil(P[0,:]).astype(int)
     19     Px_dn = np.floor(P[0,:]).astype(int)

ipdb> q
---------------------------------------------------------------------------
BdbQuit                                   Traceback (most recent call last)
<ipython-input-6-53506ffaa168> in <module>
     55 
     56 
---> 57 test_bl()

<ipython-input-6-53506ffaa168> in test_bl()
     41     ])
     42     img = np.arange(5*5, dtype=float).reshape(5,5)
---> 43     bx = bilinear_approximation(P, img)
     44 #     print('Points: \n', P)
     45 #     print('img = \n', img)

<ipython-input-6-53506ffaa168> in bilinear_approximation(P, img)
     15     # find the corner values of the input pixels
     16     pdb.set_trace()
---> 17     w,h = img.shape
     18     Px_up = np.ceil(P[0,:]).astype(int)
     19     Px_dn = np.floor(P[0,:]).astype(int)

<ipython-input-6-53506ffaa168> in bilinear_approximation(P, img)
     15     # find the corner values of the input pixels
     16     pdb.set_trace()
---> 17     w,h = img.shape
     18     Px_up = np.ceil(P[0,:]).astype(int)
     19     Px_dn = np.floor(P[0,:]).astype(int)

/usr/lib/python3.6/bdb.py in trace_dispatch(self, frame, event, arg)
     49             return # None
     50         if event == 'line':
---> 51             return self.dispatch_line(frame)
     52         if event == 'call':
     53             return self.dispatch_call(frame, arg)

/usr/lib/python3.6/bdb.py in dispatch_line(self, frame)
     68         if self.stop_here(frame) or self.break_here(frame):
     69             self.user_line(frame)
---> 70             if self.quitting: raise BdbQuit
     71         return self.trace_dispatch
     72 

BdbQuit: 
In [ ]:

In [ ]: