# HG changeset patch # User Xavier Glorot # Date 1265907303 18000 # Node ID 1b8176e9892e3ebbb459b4ed639023d1e6d307d5 # Parent 7054d7afb948fb5331382f65d53d5f3ddc112c36 cleaning some *.pyc and *.py~ files in pycapcha diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/Base.pyc Binary file pycaptcha/Captcha/Base.pyc has changed diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/File.pyc Binary file pycaptcha/Captcha/File.pyc has changed diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/Visual/Backgrounds.pyc Binary file pycaptcha/Captcha/Visual/Backgrounds.pyc has changed diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/Visual/Base.pyc Binary file pycaptcha/Captcha/Visual/Base.pyc has changed diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/Visual/Base.py~ --- a/pycaptcha/Captcha/Visual/Base.py~ Thu Feb 11 11:23:35 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -""" Captcha.Visual.BAse - -Base classes for visual CAPTCHAs. We use the Python Imaging Library -to manipulate these images. -""" -# -# PyCAPTCHA Package -# Copyright (C) 2004 Micah Dowty -# - -import Captcha -import Image - -__all__ = ['ImageCaptcha', 'Layer'] - - -class ImageCaptcha(Captcha.BaseCaptcha): - """Base class for image-based CAPTCHA tests. - The render() function generates the CAPTCHA image at the given size by - combining Layer instances from self.layers, which should be created by - the subclass-defined getLayers(). - """ - defaultSize = (256,96) - - def __init__(self, *args, **kwargs): - Captcha.BaseCaptcha.__init__(self) - self._layers = self.getLayers(*args, **kwargs) - - def getImage(self): - """Get a PIL image representing this CAPTCHA test, creating it if necessary""" - if not self._image: - self._image = self.render() - return self._image - - def getLayers(self): - """Subclasses must override this to return a list of Layer instances to render. - Lists within the list of layers are recursively rendered. - """ - return [] - - def render(self, size=None): - """Render this CAPTCHA, returning a PIL image""" - if size is None: - size = self.defaultSize - img = Image.new("RGB", size) - return self._renderList(self._layers, Image.new("RGB", size)) - - def _renderList(self, l, img): - for i in l: - if type(i) == tuple or type(i) == list: - img = self._renderList(i, img) - else: - img = i.render(img) or img - return img - - -class Layer(object): - """A renderable object representing part of a CAPTCHA. - The render() function should return approximately the same result, regardless - of the image size. This means any randomization must occur in the constructor. - - If the render() function returns something non-None, it is taken as an image to - replace the current image with. This can be used to implement transformations - that result in a separate image without having to copy the results back to the first. - """ - def render(self, img): - pass - -### The End ### diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/Visual/Distortions.pyc Binary file pycaptcha/Captcha/Visual/Distortions.pyc has changed diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/Visual/Distortions.py~ --- a/pycaptcha/Captcha/Visual/Distortions.py~ Thu Feb 11 11:23:35 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -""" Captcha.Visual.Distortions - -Distortion layers for visual CAPTCHAs -""" -# -# PyCAPTCHA Package -# Copyright (C) 2004 Micah Dowty -# - -from Captcha.Visual import Layer -import ImageDraw, Image -import random, math - - -class WigglyBlocks(Layer): - """Randomly select and shift blocks of the image""" - def __init__(self, blockSize=3, sigma=0.01, iterations=300): - self.blockSize = blockSize - self.sigma = sigma - self.iterations = iterations - self.seed = random.random() - - def render(self, image): - r = random.Random(self.seed) - for i in xrange(self.iterations): - # Select a block - bx = int(r.uniform(0, image.size[0]-self.blockSize)) - by = int(r.uniform(0, image.size[1]-self.blockSize)) - block = image.crop((bx, by, bx+self.blockSize-1, by+self.blockSize-1)) - - # Figure out how much to move it. - # The call to floor() is important so we always round toward - # 0 rather than to -inf. Just int() would bias the block motion. - mx = int(math.floor(r.normalvariate(0, self.sigma))) - my = int(math.floor(r.normalvariate(0, self.sigma))) - - # Now actually move the block - image.paste(block, (bx+mx, by+my)) - - -class WarpBase(Layer): - """Abstract base class for image warping. Subclasses define a - function that maps points in the output image to points in the input image. - This warping engine runs a grid of points through this transform and uses - PIL's mesh transform to warp the image. - """ - filtering = Image.BILINEAR - resolution = 10 - - def getTransform(self, image): - """Return a transformation function, subclasses should override this""" - return lambda x, y: (x, y) - - def render(self, image): - r = self.resolution - xPoints = image.size[0] / r + 2 - yPoints = image.size[1] / r + 2 - f = self.getTransform(image) - - # Create a list of arrays with transformed points - xRows = [] - yRows = [] - for j in xrange(yPoints): - xRow = [] - yRow = [] - for i in xrange(xPoints): - x, y = f(i*r, j*r) - - # Clamp the edges so we don't get black undefined areas - x = max(0, min(image.size[0]-1, x)) - y = max(0, min(image.size[1]-1, y)) - - xRow.append(x) - yRow.append(y) - xRows.append(xRow) - yRows.append(yRow) - - # Create the mesh list, with a transformation for - # each square between points on the grid - mesh = [] - for j in xrange(yPoints-1): - for i in xrange(xPoints-1): - mesh.append(( - # Destination rectangle - (i*r, j*r, - (i+1)*r, (j+1)*r), - # Source quadrilateral - (xRows[j ][i ], yRows[j ][i ], - xRows[j+1][i ], yRows[j+1][i ], - xRows[j+1][i+1], yRows[j+1][i+1], - xRows[j ][i+1], yRows[j ][i+1]), - )) - - return image.transform(image.size, Image.MESH, mesh, self.filtering) - - -class SineWarp(WarpBase): - """Warp the image using a random composition of sine waves""" - - def __init__(self, - amplitudeRange = (3, 6.5), - periodRange = (0.04, 0.1), - ): - self.amplitude = random.uniform(*amplitudeRange) - self.period = random.uniform(*periodRange) - self.offset = (random.uniform(0, math.pi * 2 / self.period), - random.uniform(0, math.pi * 2 / self.period)) - - def getTransform(self, image): - return (lambda x, y, - a = self.amplitude, - p = self.period, - o = self.offset: - (math.sin( (y+o[0])*p )*a + x, - math.sin( (x+o[1])*p )*a + y)) - -### The End ### diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/Visual/Pictures.pyc Binary file pycaptcha/Captcha/Visual/Pictures.pyc has changed diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/Visual/Tests.pyc Binary file pycaptcha/Captcha/Visual/Tests.pyc has changed diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/Visual/Tests.py~ --- a/pycaptcha/Captcha/Visual/Tests.py~ Thu Feb 11 11:23:35 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -""" Captcha.Visual.Tests - -Visual CAPTCHA tests -""" -# -# PyCAPTCHA Package -# Copyright (C) 2004 Micah Dowty -# - -from Captcha.Visual import Text, Backgrounds, Distortions, ImageCaptcha -from Captcha import Words -import random - -__all__ = ["PseudoGimpy", "AngryGimpy", "AntiSpam"] - - -class PseudoGimpy(ImageCaptcha): - """A relatively easy CAPTCHA that's somewhat easy on the eyes""" - def getLayers(self): - word = Words.defaultWordList.pick() - self.addSolution(word) - return [ - # random.choice([ - # Backgrounds.CroppedImage(), - # Backgrounds.TiledImage(), - # ]), - Text.TextLayer(word, borderSize=1), - Distortions.SineWarp(), - ] - - -class AngryGimpy(ImageCaptcha): - """A harder but less visually pleasing CAPTCHA""" - def getLayers(self): - word = Words.defaultWordList.pick() - self.addSolution(word) - return [ - # suppression du background - # Backgrounds.TiledImage(), - # Backgrounds.RandomDots(), - Text.TextLayer(word, borderSize=1), - Distortions.SineWarp(periodRange = (0.04, 0.07)) - # Distortions.WigglyBlocks(), - ] - - -class AntiSpam(ImageCaptcha): - """A fixed-solution CAPTCHA that can be used to hide email addresses or URLs from bots""" - fontFactory = Text.FontFactory(20, "vera/VeraBd.ttf") - defaultSize = (512,50) - - def getLayers(self, solution="murray@example.com"): - self.addSolution(solution) - - textLayer = Text.TextLayer(solution, - borderSize = 2, - fontFactory = self.fontFactory) - - return [ - Backgrounds.CroppedImage(), - textLayer, - Distortions.SineWarp(amplitudeRange = (3, 5)), - ] - -### The End ### diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/Visual/Text.pyc Binary file pycaptcha/Captcha/Visual/Text.pyc has changed diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/Visual/Text.py~ --- a/pycaptcha/Captcha/Visual/Text.py~ Thu Feb 11 11:23:35 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -""" Captcha.Visual.Text - -Text generation for visual CAPTCHAs. -""" -# -# PyCAPTCHA Package -# Copyright (C) 2004 Micah Dowty -# - -import random, os -from Captcha import Visual, File -import ImageFont, ImageDraw - - -class FontFactory(File.RandomFileFactory): - """Picks random fonts and/or sizes from a given list. - 'sizes' can be a single size or a (min,max) tuple. - If any of the given files are directories, all *.ttf found - in that directory will be added. - """ - extensions = [".ttf", ".bdf"] - basePath = "fonts" - -# arguments variables a modifier pour mettre le chemin vers les fontes. - def __init__(self, sizes, *fileNames): - File.RandomFileFactory.__init__(self, *fileNames) - - if type(sizes) is tuple: - self.minSize = sizes[0] - self.maxSize = sizes[1] - else: - self.minSize = sizes - self.maxSize = sizes - - def pick(self): - """Returns a (fileName, size) tuple that can be passed to ImageFont.truetype()""" - fileName = File.RandomFileFactory.pick(self) - size = int(random.uniform(self.minSize, self.maxSize) + 0.5) - return (fileName, size) - -# Predefined font factories -defaultFontFactory = FontFactory(25, "vera", "mlm", "others") -#defaultFontFactory = FontFactory((30, 40), "vera") - -class TextLayer(Visual.Layer): - """Represents a piece of text rendered within the image. - Alignment is given such that (0,0) places the text in the - top-left corner and (1,1) places it in the bottom-left. - - The font and alignment are optional, if not specified one is - chosen randomly. If no font factory is specified, the default is used. - """ - def __init__(self, text, - alignment = None, - font = None, - fontFactory = None, - textColor = "white", - borderSize = 0, - borderColor = None, - ): - if fontFactory is None: - global defaultFontFactory - fontFactory = defaultFontFactory - - if font is None: - font = fontFactory.pick() - - if alignment is None: - alignment = (random.uniform(0,1), - random.uniform(0,1)) - - self.text = text - self.alignment = alignment - self.font = font - self.textColor = textColor - self.borderSize = borderSize - self.borderColor = borderColor - - def render(self, img): - font = ImageFont.truetype(*self.font) - textSize = font.getsize(self.text) - draw = ImageDraw.Draw(img) - - # Find the text's origin given our alignment and current image size - x = int((img.size[0] - textSize[0] - self.borderSize*2) * self.alignment[0] + 0.5) - y = int((img.size[1] - textSize[1] - self.borderSize*2) * self.alignment[1] + 0.5) - - # Draw the border if we need one. This is slow and ugly, but there doesn't - # seem to be a better way with PIL. - if self.borderSize > 0: - for bx in (-1,0,1): - for by in (-1,0,1): - if bx and by: - draw.text((x + bx * self.borderSize, - y + by * self.borderSize), - self.text, font=font, fill=self.borderColor) - - # And the text itself... - draw.text((x,y), self.text, font=font, fill=self.textColor) - -### The End ### diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/Visual/__init__.pyc Binary file pycaptcha/Captcha/Visual/__init__.pyc has changed diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/Words.pyc Binary file pycaptcha/Captcha/Words.pyc has changed diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/Words.py~ --- a/pycaptcha/Captcha/Words.py~ Thu Feb 11 11:23:35 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -""" Captcha.Words - -Utilities for managing word lists and finding random words -""" -# -# PyCAPTCHA Package -# Copyright (C) 2004 Micah Dowty -# - -import random, os -import File - - -class WordList(object): - """A class representing a word list read from disk lazily. - Blank lines and comment lines starting with '#' are ignored. - Any number of words per line may be used. The list can - optionally ingore words not within a given length range. - """ - def __init__(self, fileName, minLength=None, maxLength=None): - self.words = None - self.fileName = fileName - self.minLength = minLength - self.maxLength = maxLength - - def read(self): - """Read words from disk""" - f = open(os.path.join(File.dataDir, "words", self.fileName)) - - self.words = [] - for line in f.xreadlines(): - line = line.strip() - if not line: - continue - if line[0] == '#': - continue - for word in line.split(): - if self.minLength is not None and len(word) < self.minLength: - continue - if self.maxLength is not None and len(word) > self.maxLength: - continue - self.words.append(word) - - def pick(self): - """Pick a random word from the list, reading it in if necessary""" - if self.words is None: - self.read() - return random.choice(self.words) - - -# Define several shared word lists that are read from disk on demand -basic_english = WordList("basic-english") -basic_english_restricted = WordList("basic-english", minLength=5, maxLength=8) - -defaultWordList = basic_english_restricted - -### The End ### diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Captcha/__init__.pyc Binary file pycaptcha/Captcha/__init__.pyc has changed diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Facade.pyc Binary file pycaptcha/Facade.pyc has changed diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/Facade.py~ --- a/pycaptcha/Facade.py~ Thu Feb 11 11:23:35 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -#!/usr/bin/env python - - - -from Captcha.Visual.Tests import PseudoGimpy, AngryGimpy -import numpy - -# Une fonction simple pour generer un captcha -# ease : represente la difficulte du captcha a generer -# 0 = facile et 1 (ou autre chose) = difficile -#solution : specifie si on veut en retour un array numpy representant -#l image ou un tuple contenant l'array et la solution du captcha. - -# Des fontes additionnelles peuvent etre ajoutees au dossier pyCaptcha/Captcha/data/fonts/others -# Le programme choisit une fonte aleatoirement dans ce dossier ainsi que le dossir vera. - - -def generateCaptcha (ease=0, solution=0): - - if ease == 1: - g = AngryGimpy() - - else: - g = PseudoGimpy() - - i = g.render() - a = numpy.asarray(i) - - if solution == 0: - return a - - else : - return (a, g,solutions) diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/simple_example.py~ --- a/pycaptcha/simple_example.py~ Thu Feb 11 11:23:35 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -#!/usr/bin/env python -# -# A very simple example that creates a random image from the -# PseudoGimpy CAPTCHA, saves and shows it, and prints the list -# of solutions. Normally you would call testSolutions rather -# than reading this list yourself. -# -from Captcha.Visual.Tests import PseudoGimpy, AngryGimpy -import numpy -#from numpy import * - -g = AngryGimpy() -i = g.render() -a = numpy.asarray(i) -b = numpy.zeros((2, 2), numpy.int8) -c = a == b -print c -i.save("output.png") -i.show() -#print a -#print g.solutions diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/transformations.pyc Binary file pycaptcha/transformations.pyc has changed diff -r 7054d7afb948 -r 1b8176e9892e pycaptcha/transformations.py~ --- a/pycaptcha/transformations.py~ Thu Feb 11 11:23:35 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ - -import Numeric, Image - """ Transforme une image PIL en objet numpy.array et vice versa""" - - -def image2array(im): - """ image vers array numpy""" - if im.mode not in ("L", "F"): - raise ValueError, "can only convert single-layer images" - if im.mode == "L": - a = Numeric.fromstring(im.tostring(), Numeric.UnsignedInt8) - else: - a = Numeric.fromstring(im.tostring(), Numeric.Float32) - a.shape = im.size[1], im.size[0] - return a - -def array2image(a): - """ array numpy vers image""" - if a.typecode() == Numeric.UnsignedInt8: - mode = "L" - elif a.typecode() == Numeric.Float32: - mode = "F" - else: - raise ValueError, "unsupported image mode" - return Image.fromstring(mode, (a.shape[1], a.shape[0]), a.tostring()) diff -r 7054d7afb948 -r 1b8176e9892e transformations/testtransformations.py --- a/transformations/testtransformations.py Thu Feb 11 11:23:35 2010 -0500 +++ b/transformations/testtransformations.py Thu Feb 11 11:55:03 2010 -0500 @@ -28,7 +28,8 @@ MODULE_INSTANCES = [Slant(),Thick(),AffineTransformation(),LocalElasticDistorter(),GIMP1(), PermutPixel(),DistorsionGauss(), Rature(), Occlusion(),AddBackground(), BruitGauss(),PoivreSel(), Contrast()] ###---------------------complexity associated to each of them -complexity = [0.7,0.7,0.7,0.7,0.7,0.3,0.3,0.5,0.5,0.1,0.3,0.3,0.5] +complexity = [0.6,0.6,0.6,0.6,0.6,0.3,0.3,0.5,0.5,0.5,0.3,0.3,0.5] +complexity = [0.5]*len(MODULE_INSTANCES) #complexity = [0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.] @@ -52,7 +53,7 @@ pygame.font.init() -for i in range(10000): +for i in range(1000): a=d[i,:] b=N.asarray(N.reshape(a,(32,32))) c=N.asarray([N.reshape(a*255.0,(32,32))]*3).T @@ -88,7 +89,7 @@ else: offset += 4*32 ct+=1 - pygame.image.save(screen,'/u/glorotxa/exemples/%s.BMP'%i) + pygame.image.save(screen,'/u/glorotxa/exemples/%s.PNG'%i) #raw_input('Press Enter') #pygame.display.quit()