Changeset 2031


Ignore:
Timestamp:
11/20/07 00:04:32 (6 years ago)
Author:
sam
Message:
  • More about photomosaics.
Location:
www/study
Files:
3 added
2 edited
2 moved

Legend:

Unmodified
Added
Removed
  • www/study/part6.html

    r2030 r2031  
    4040of a bigger image. </p> 
    4141 
    42 <p> Since we don’t have many images at our disposition, we will simply 
    43 cut Lenna into small chunks and use these parts to create mosaics. This is 
    44 our <b>image database</b>: </p> 
     42<p> Since we don’t have many images at our disposal, we will simply cut Lenna 
     43into small chunks (called <b>tiles</b>) and use these parts to create mosaics. 
     44This is our <b>tile database</b>: </p> 
    4545 
    4646<p style="text-align: center;"> 
     
    4949</p> 
    5050 
    51 <p> Here is an example of a simple photographic mosaic method where the 
    52 original picture is cut into smaller chunks and each chunk is matched to 
    53 the most resembling item in the image database: </p> 
     51<p> Generating a photomosaic consists in subdividing the original picture 
     52into <i>x</i> rectangular cells and find <i>x</i> tiles in the database 
     53(with or without duplicates, depending on the set of rules that is decided) 
     54so that when recombined the resulting image resembles the original picture. 
     55By the way, this technique is covered by Runaway Technology Inc’s 
     56<a href="http://www.freepatentsonline.com/6137498.html">U.S. patent 
     576137498</a>. </p> 
     58 
     59<p> Picking the right tile for the right cell in the grid is a very 
     60expensive and complicated operation. One of the biggest problems is the 
     61cost of a database lookup: comparing each tile area pixel-by-pixel 
     62is an O(N) operation where N is the size of the database. We can resort 
     63to <b>image classification</b> in order to speed up database lookups. </p> 
     64 
     65<h3> 6.1. Image classification </h3> 
     66 
     67<p> One of the simplest image classification technique is the storage of 
     68each tile’s <b>average colour</b> into a separate database that is used for 
     69best match lookups: </p> 
    5470 
    5571<p style="text-align: center;"> 
    56   <img src="out6-0-2.png" width="80" height="80" 
     72  <img src="out6-1-1.png" width="168" height="120" 
     73       class="inline" alt="1 feature extracted from Lenna patterns" /> 
     74</p> 
     75 
     76<p> When creating the mosaic, we then only need to check the average colour 
     77instead of comparing each pixel one by one. Below is the result of the 
     78technique applied on a portion of the Lenna picture: </p> 
     79 
     80<p style="text-align: center;"> 
     81  <img src="out6-1-2.png" width="80" height="80" 
    5782       class="inlinetop" alt="Lenna (detail)" /> 
    58   <img src="out6-0-3.png" width="416" height="416" 
     83  <img src="out6-1-3.png" width="416" height="416" 
     84       class="inline" alt="Mosaic created from Lenna’s detail" /> 
     85</p> 
     86 
     87<p> Better results can be achieved by storing <b>four colour values</b>, one 
     88for each corner of the tile: </p> 
     89 
     90<p style="text-align: center;"> 
     91  <img src="out6-1-4.png" width="248" height="176" 
     92       class="inline" alt="4 features extracted from Lenna patterns" /> 
     93</p> 
     94 
     95<p> Having 12 values (4 RGB triplets) is still a lot less than the original 
     96value of 3072 (for 32×32 tiles), and the results show clear improvement, 
     97for instance the feather-hair frontier is now a lot smoother: </p> 
     98 
     99<p style="text-align: center;"> 
     100  <img src="out6-1-2.png" width="80" height="80" 
     101       class="inlinetop" alt="Lenna (detail)" /> 
     102  <img src="out6-1-5.png" width="416" height="416" 
    59103       class="inline" alt="Mosaic created from Lenna’s detail" /> 
    60104</p> 
  • www/study/study.py

    r2030 r2031  
    3939        c = self.colorResolve((r, g, b)) 
    4040        self.setPixel((x, y), c) 
     41    def getCrop(self, x, y, w, h): 
     42        dest = Image((w, h), True) 
     43        self.copyTo(dest, (-x, -y)) 
     44        return dest 
    4145 
    4246# Manipulate gamma values 
     
    838842    return coeffs 
    839843 
    840 def test603(src, sqw, sqh, tnlist, coeffs, dx, dy): 
    841     (w, h) = src.size() 
     844def test601(tnlist, cols): 
    842845    (tnw, tnh) = tnlist[0].size() 
     846    dw = cols 
     847    dh = (len(tnlist) + cols - 1) / cols 
     848    dest = Image((dw * tnw + 8 * (dw + 1), dh * tnh + 8 * (dh + 1)), True) 
     849    for (n, img) in enumerate(tnlist): 
     850        di = 8 + (n % dw) * (tnw + 8) 
     851        dj = 8 + (n / dw) * (tnh + 8) 
     852        for y in range(tnh): 
     853            for x in range(tnw): 
     854                (r, g, b) = img.getRgb(x, y) 
     855                dest.setRgb(di + x, dj + y, r, g, b) 
     856    return dest 
     857 
     858if chapter(6): 
     859    tnlist = mosaic_split(lenna256, 32, 32) 
     860    test601(tnlist, 10).save("out6-0-1.png") 
     861 
     862# Output 6.1.1: extract 1 colour feature from mosaic tiles 
     863# Output 6.1.2: crop Lenna 
     864# Output 6.1.3: generate a mosaic from the 1-feature database 
     865# Output 6.1.4: extract 4 colour features from mosaic tiles 
     866# Output 6.1.5: generate a mosaic from the 4-feature database 
     867def test61x(coeffs, cols, tnw, tnh): 
     868    dx = len(coeffs[0][0]) 
     869    dy = len(coeffs[0]) 
     870    dw = cols 
     871    dh = (len(coeffs) + cols - 1) / cols 
     872    dest = Image((dw * tnw + 8 * (dw + 1), dh * tnh + 8 * (dh + 1)), True) 
     873    for (n, tab) in enumerate(coeffs): 
     874        di = 8 + (n % dw) * (tnw + 8) 
     875        dj = 8 + (n / dw) * (tnh + 8) 
     876        for y in range(tnh): 
     877            for x in range(tnw): 
     878                (r, g, b) = tab[y * dy / tnh][x * dx / tnw] 
     879                dest.setRgb(di + x, dj + y, Gamma.ItoC(r), Gamma.ItoC(g), Gamma.ItoC(b)) 
     880    return dest 
     881 
     882def test61y(src, sqw, sqh, tnlist, coeffs): 
     883    (w, h) = src.size() 
     884    (tnw, tnh) = tnlist[0].size() 
     885    dx = len(coeffs[0][0]) 
     886    dy = len(coeffs[0]) 
    843887    nx = w / sqw 
    844888    ny = h / sqh 
     
    873917    return dest 
    874918 
    875 def test602(src, x, y, w, h): 
    876     dest = Image((w, h), True) 
    877     src.copyTo(dest, (-x, -y)) 
    878     return dest 
    879  
    880 def test601(tnlist, cols): 
    881     (tnw, tnh) = tnlist[0].size() 
    882     dw = cols 
    883     dh = (len(tnlist) + cols - 1) / cols 
    884     dest = Image((dw * tnw + 8 * (dw + 1), dh * tnh + 8 * (dh + 1)), True) 
    885     for (n, img) in enumerate(tnlist): 
    886         di = 8 + (n % dw) * (tnw + 8) 
    887         dj = 8 + (n / dw) * (tnh + 8) 
    888         for y in range(tnh): 
    889             for x in range(tnw): 
    890                 (r, g, b) = img.getRgb(x, y) 
    891                 dest.setRgb(di + x, dj + y, r, g, b) 
    892     return dest 
    893  
    894919if chapter(6): 
    895     tnlist = mosaic_split(lenna256, 32, 32) 
    896     coeffs = mosaic_analyse(tnlist, 2, 2) 
    897     test601(tnlist, 10).save("out6-0-1.png") 
    898     out602 = test602(lenna256, 100, 90, 80, 80) 
    899     out602.save("out6-0-2.png") 
    900     test603(out602, 6, 6, tnlist, coeffs, 2, 2).save("out6-0-3.png") 
     920    coeffs1x1 = mosaic_analyse(tnlist, 1, 1) 
     921    test61x(coeffs1x1, 10, 8, 8).save("out6-1-1.png") 
     922    out612 = lenna256.getCrop(100, 90, 80, 80) 
     923    out612.save("out6-1-2.png") 
     924    test61y(out612, 6, 6, tnlist, coeffs1x1).save("out6-1-3.png") 
     925 
     926    coeffs2x2 = mosaic_analyse(tnlist, 2, 2) 
     927    test61x(coeffs2x2, 10, 16, 16).save("out6-1-4.png") 
     928    test61y(out612, 6, 6, tnlist, coeffs2x2).save("out6-1-5.png") 
    901929 
    902930############################################################################## 
Note: See TracChangeset for help on using the changeset viewer.