started examples page
This commit is contained in:
parent
ab7bd3000b
commit
f7b01ed930
2
TODO
2
TODO
@ -1,3 +1,5 @@
|
||||
- add analytics tags to docs output
|
||||
|
||||
- not sure about utf8 error messages on win
|
||||
|
||||
- strange:
|
||||
|
297
doc/Examples.md
Normal file
297
doc/Examples.md
Normal file
@ -0,0 +1,297 @@
|
||||
<refmeta>
|
||||
<refentrytitle>Using `vipsthumbnail`</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
<refmiscinfo>libvips</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>`vipsthumbnail`</refname>
|
||||
<refpurpose>Introduction to `vipsthumbnail`, with examples</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
This page shows a few examples of using VIPS from Python.
|
||||
|
||||
# Average a region of interest box on an image
|
||||
|
||||
``` python
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import gi
|
||||
gi.require_version('Vips', '8.0')
|
||||
from gi.repository import Vips
|
||||
|
||||
roix = 10
|
||||
roiy = 10
|
||||
roiw = 64
|
||||
roih = 64
|
||||
|
||||
image = Vips.Image.new_from_file(sys.argv[1])
|
||||
roi = image.crop(roix, roiy, roiw, roih)
|
||||
print 'average: ', roi.avg()
|
||||
```
|
||||
|
||||
# VIPS and PIL
|
||||
|
||||
This script moves an image between PIL and VIPS.
|
||||
|
||||
``` python
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
|
||||
from vipsCC import *
|
||||
import Image
|
||||
|
||||
# try this 1,000 times and check for leaks
|
||||
for i in range (0,1000):
|
||||
vim = VImage.VImage (sys.argv[1])
|
||||
|
||||
# do some processing in vips ... cut out a small piece of image
|
||||
vim = vim.extract_area (500, 500, 100, 100)
|
||||
|
||||
# make a PIL image
|
||||
# we use Image.frombuffer (), so PIL is using vim's memory
|
||||
# you need to be very careful not to destroy vim until you're done with pim
|
||||
# ideally you should make a proxy class that wraps this lifetime problem up
|
||||
mode = VImage.PIL_mode_from_vips (vim)
|
||||
size = (vim.Xsize (), vim.Ysize ())
|
||||
data = vim.tobuffer ()
|
||||
pim = Image.frombuffer (mode, size, data, 'raw', mode, 0, 1)
|
||||
|
||||
# rotate 12 degrees with PIL
|
||||
pim = pim.rotate (12, Image.BILINEAR, 1)
|
||||
|
||||
# back to vips again
|
||||
# PIL doesn't have a tobuffer method, so we have to use tostring to copy the
|
||||
# data out of PIL and then fromstring to copy back into VIPS
|
||||
str = pim.tostring ()
|
||||
bands, format, type = VImage.vips_from_PIL_mode (pim.mode)
|
||||
width, height = pim.size
|
||||
vim2 = VImage.VImage.fromstring (str, width, height, bands, format)
|
||||
|
||||
# finally write from vips
|
||||
vim2.write (sys.argv[2])
|
||||
```
|
||||
|
||||
Leak testing
|
||||
------------
|
||||
|
||||
This loads an image, does some simple processing, and saves again. Handy for leak testing.
|
||||
|
||||
``` python
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
|
||||
# just need this for leaktesting
|
||||
import gc
|
||||
|
||||
from vipsCC import *
|
||||
|
||||
if len (sys.argv) != 3:
|
||||
print 'usage:', sys.argv[0], 'inputimage outputimage'
|
||||
sys.exit (1)
|
||||
|
||||
try:
|
||||
a = VImage.VImage (sys.argv[1])
|
||||
b = a.invert ()
|
||||
c = b.lin ([1,2,3],[4,5,6])
|
||||
m = VMask.VIMask (3, 3, 1, 0,
|
||||
[-1, -1, -1,
|
||||
-1, 8, -1,
|
||||
-1, -1, -1])
|
||||
d = a.conv (m)
|
||||
d.write (sys.argv[2])
|
||||
except VError.VError, e:
|
||||
e.perror (sys.argv[0])
|
||||
|
||||
# we can get properties of VImage too
|
||||
print 'inputimage is', a.Xsize (), 'pixels across'
|
||||
|
||||
print 'starting shutdown ...'
|
||||
del b
|
||||
del a
|
||||
del c
|
||||
del d
|
||||
del m
|
||||
# sometimes have to do several GCs to get them all, not sure why
|
||||
for i in range(10):
|
||||
gc.collect ()
|
||||
print 'shutdown!'
|
||||
|
||||
print 'leaked IMAGEs:'
|
||||
VImage.im__print_all ()
|
||||
print 'done ... hopefully you saw no leaks'
|
||||
```
|
||||
|
||||
Build image mosaic
|
||||
------------------
|
||||
|
||||
This loads a lot of images (RGB or greyscale) and pastes them at random positions in a 10,000 by 10,000 pixel output image. 8-bit only, but it'd be easy to change that.
|
||||
|
||||
``` python
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
import random
|
||||
from vipsCC import *
|
||||
|
||||
# the size of the image we build
|
||||
size = 10000
|
||||
|
||||
try:
|
||||
if len(sys.argv) < 3:
|
||||
print 'usage:', sys.argv[0], 'outfile infile1 ...'
|
||||
sys.exit (1)
|
||||
|
||||
# make the background image
|
||||
bg = VImage.VImage.black (size, size, 3)
|
||||
|
||||
# paste each argument in
|
||||
for file in sys.argv[2:]:
|
||||
im = VImage.VImage (file)
|
||||
|
||||
# is this a mono image? convert to RGB by joining three of them
|
||||
# together
|
||||
if im.Bands() == 1:
|
||||
im = im.bandjoin (im).bandjoin (im)
|
||||
|
||||
x = random.randint (0, size - im.Xsize () - 1)
|
||||
y = random.randint (0, size - im.Ysize () - 1)
|
||||
bg = bg.insert_noexpand (im, x, y)
|
||||
|
||||
# write result
|
||||
bg.write (sys.argv[1])
|
||||
|
||||
except VError.VError, e:
|
||||
e.perror (sys.argv[0])
|
||||
```
|
||||
|
||||
Build image pyramid
|
||||
-------------------
|
||||
|
||||
This makes a tiled image pyramid, with each tile in a separate 512x512 pixel file.
|
||||
|
||||
``` python
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
from vipsCC import *
|
||||
|
||||
tilesize = 512
|
||||
maxlevel = 100
|
||||
|
||||
try:
|
||||
im = VImage.VImage (sys.argv[1])
|
||||
|
||||
for level in range (maxlevel, -1, -1):
|
||||
print "Creating tiles for level", level
|
||||
|
||||
# loop to create the tiles
|
||||
for y in range (0, im.Ysize(), tilesize):
|
||||
for x in range (0, im.Xsize(), tilesize):
|
||||
filename = '%dx%d_y%d.jpg' % (level, x / tilesize, y / tilesize)
|
||||
# clip tilesize against image size
|
||||
width = min (im.Xsize () - x, tilesize)
|
||||
height = min (im.Ysize () - y, tilesize)
|
||||
|
||||
# expand edge tiles up to the full tilesize ... Google maps likes this
|
||||
# im.extract_area (x, y, width, height).embed(0, 0, 0, tilesize, tilesize).write(filename)
|
||||
|
||||
# let edge tiles be smaller than the full tile size, tiff tiling prefers this
|
||||
im.extract_area (x, y, width, height).write (filename)
|
||||
|
||||
# was there only a single tile? we are done
|
||||
if im.Xsize() <= tilesize and im.Ysize() <= tilesize:
|
||||
break
|
||||
|
||||
# create next pyramid level in RAM
|
||||
shrink = im.rightshift_size (1, 1, im.BandFmt())
|
||||
im = shrink.write (VImage.VImage ("temp", "t"))
|
||||
|
||||
except VError.VError, e:
|
||||
e.perror (sys.argv[0])
|
||||
```
|
||||
|
||||
Rename DICOM images using header fields
|
||||
---------------------------------------
|
||||
|
||||
DICOM images commonly come in an awful directory hierarchy named as something like images/a/b/e/z04. There can be thousands of files and it can be very hard to find the one you want.
|
||||
|
||||
This utility copies files to a single flat directory, naming them using fields from the DICOM header. You can actually find stuff! Useful.
|
||||
|
||||
``` python
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from vipsCC import *
|
||||
|
||||
if len (sys.argv) != 3:
|
||||
print 'rename DICOM files using tags from the header'
|
||||
print 'usage:'
|
||||
print '\t%s srcdir destdir' % sys.argv[0]
|
||||
print 'the directory tree below srcdir is searched, all files are'
|
||||
print 'renamed and put into destdir in a flat list'
|
||||
sys.exit (1)
|
||||
|
||||
srcdir = sys.argv[1]
|
||||
destdir = sys.argv[2]
|
||||
|
||||
if not os.access (destdir, os.F_OK | os.R_OK | os.W_OK | os.X_OK):
|
||||
os.mkdir (destdir)
|
||||
|
||||
def get_field (vim, field):
|
||||
result = vim.meta_get_string (field)
|
||||
|
||||
# remove any \n etc.
|
||||
result = re.sub ("\n", "", result)
|
||||
|
||||
# remove any leading or trailing spaces
|
||||
result = re.sub (" $", "", result)
|
||||
result = re.sub ("^ ", "", result)
|
||||
|
||||
return result
|
||||
|
||||
id_name = "magick-dcm:Patient'sID"
|
||||
modality_name = "magick-dcm:Modality"
|
||||
series_name = "magick-dcm:SeriesNumber"
|
||||
instance_name = "magick-dcm:Instance(formerlyImage)Number"
|
||||
date_name = "magick-dcm:ImageDate"
|
||||
|
||||
n_processed = 0
|
||||
|
||||
for (dirpath, dirnames, filenames) in os.walk (srcdir):
|
||||
for file in filenames:
|
||||
path = os.path.join (dirpath, file)
|
||||
|
||||
try:
|
||||
vim = VImage.VImage (path)
|
||||
except VError.VError, e:
|
||||
print 'unable to open', path
|
||||
continue
|
||||
|
||||
try:
|
||||
id = get_field (vim, id_name)
|
||||
modality = get_field (vim, modality_name)
|
||||
series = get_field (vim, series_name)
|
||||
instance = get_field (vim, instance_name)
|
||||
date = get_field (vim, date_name)
|
||||
except VError.VError, e:
|
||||
print 'unable to get fields from header', path
|
||||
continue
|
||||
|
||||
match = re.match ("(\d\d\d\d)(\d\d)(\d\d)", date)
|
||||
date = match.group (1) + "." + match.group (2) + "." + match.group (3)
|
||||
newname = id + "." + modality + "." + series + "." + instance + "." + date + ".IMA"
|
||||
|
||||
shutil.copyfile(path, os.path.join (destdir, newname))
|
||||
|
||||
n_processed += 1
|
||||
|
||||
print '\t(%d files processed)' % n_processed
|
||||
```
|
Loading…
x
Reference in New Issue
Block a user