#! /usr/bin/env python
## -*- coding: utf-8 -*-
## (C) 2012: Hans Georg Schaathun <georg@schaathun.net>
"""
Functions to load image sets into the database and define
test and training sets.
This is rather crude and it may be better to consult the scripts
to see how the functions are used.
"""
from . import *
import os
import numpy.random as rnd
import numpy as np
from .aux import isDuplicateError
rnd.seed()
import ConfigParser
__all__ = [ "loadImages", "similarTestSet", "makeTestSets",
"groupTestSet", "dummyTestSet", ]
[docs]def loadImages( fn ):
"""
Define image sets based on a config file with the given filename fn.
"""
cfg = ConfigParser.SafeConfigParser( )
cfg.read( fn )
for s in cfg.sections():
kw = { "name" : s }
for o in cfg.options(s):
kw[o] = cfg.get(s,o)
if kw.has_key("source"):
kw["source"] = ImageSet.byName( kw["source"] )
try:
S = ImageSet( **kw )
except Exception as e:
print type(e)
print e
print "Not allowed to add ImageSet", kw["name"]
pass
else:
submitImages(S)
return
def submitImages( imgset ):
"""
Submit images to an ImageSet object imgset by reading the
filenames directly from the file system. If source is given,
it should be another ImageSet containing source images.
The individual source images for each derived image is
defined by the file basename and linked.
"""
verbosity = config.getVerbosity( "sql" )
dir = imgset.getPath()
fl = os.listdir( dir )
ext = imgset.extension
src = imgset.source
for fn in fl:
(fbase,fext) = fn.split( ".", 1 )
if ext != None and ext != fext: continue
if src:
source = src.getBasename( fbase )
if verbosity > 2:
print "From", source
img = Image( filename=fn, imageset=imgset, source=source )
else:
img = Image( filename=fn, imageset=imgset )
if verbosity > 1:
print img
return
[docs]def similarTestSet( base, stego, name, incomplete=False ):
"""
Create a new TestSet based on base, but using stego images
from stego instead. The same random selection is used as
in bane. (Not tested.)
"""
T = TestSet( name=name )
for img in base.testimg:
basename = img.getBasename()
if img.label == 0:
r = TestImage( image=img.image, imagesetID=T, label=0 )
print img.image
print r
else:
ext = stego.extension
try:
st = Image.selectBy( imageset=stego,
filename=basename+"."+ext ).getOne()
except:
if incomplete:
print "Missing stego image:", basename
else:
raise
else:
r = TestImage( image=st, imagesetID=T, label=1 )
print st
print r
return T
[docs]def makeTestSets( clean, stego, name, testname=None,
testsize=None, trainsize=None,skew=0.5 ):
"""
Given two image sets for clean images and steganograms respectively,
training and test sets are constructed randomly. It is assumed that
both clean and stego contain corresponding images with the same
basename, and if a clean image is included, the corresponding stego
images is excluded, and vice versa.
"""
if testname == None: testname = name + "_test"
try:
train = TestSet( name=name )
test = TestSet( name=testname )
except StandardError as e:
if not isDuplicateError(e):
raise
print "Warning! Sets already existed"
train = TestSet.byName( name )
test = TestSet.byName( testname )
return (train,test)
# Catch errors here
img = rnd.permutation(list(clean.images))
totalsize = len(img)
if testsize == None and trainsize == None:
testsize = np.floor( totalsize / 2 )
trainsize = np.ceil( totalsize / 2 )
if testsize != None and testsize <= 1:
testsize = testsize*totalsize
if trainsize != None and trainsize <= 1:
testsize = testsize*totalsize
if testsize == None: testsize = totalsize - trainsize
if trainsize == None: trainsize = totalsize - testsize
popTestSet( train, img[:trainsize], stego, skew )
popTestSet( test, img[trainsize:(testsize+trainsize)], stego, skew )
return (train,test)
[docs]def dummyTestSet( name, L ):
"""
Create a dummy TestSet by combining all images from every image set in L.
All the test images are given the label 1. This is mainly intended to
form a set of images for which classification scores can be calculated
in bulk, and not as a test or training set as such.
"""
T = TestSet( name=name )
for ims in L:
I = getImageSet(ims)
popTestSet( T, list(I), None, 1 )
def filter( name, tset, L ):
T = TestSet( name=name )
if not isinstance(tset,SQLObject):
tset = getImageSet(tset)
if isinstance(L,str):
L = getImageSet(L)
if isinstance(L,SQLObject):
L = [ im.getBasename() for im in L ]
for im in tset:
if im.getBasename() in L:
print TestImage( image=im(), imageset=T,
label=im.label, response=im.response )
def popTestSet( set, images, stego, skew ):
"""Populate a Test or Training Set with images from a list.
This is an auxiliary function for makeTestSets()."""
N = len(images)
N1 = N*skew
print type(set), N, N1
for img in images[:N1]:
TestImage( image=img, imagesetID=set, label=0 )
for img0 in images[N1:]:
img = stego.getBasename( img0.getBasename() )
TestImage( image=img, imagesetID=set, label=1 )
[docs]def groupTestSet( set, name, feature, min=None, max=None,
create=True, **kw ):
"""Return a new TestSet object with the given name, created
by taking the images from set which satisfy min <= feature < max.
If min or max is None, it poses no constraint.
"""
L = [ (im,im.getOneFeature(feature)) for im in set ]
if max == None:
c = lambda v : ( v >= min )
elif min == None:
c = lambda v : v < max
else:
c = lambda v : v < max and v >= min
V = [ v for (im,v) in L ]
L = [ (im,v) for (im,v) in L if c(v) ]
if create:
tset = TestSet( name=name, **kw )
for (im,v) in L:
im.copy(tset)
return tset
else:
return len(L)