Прочитав статью Каптча 3d решил переписать код под PIL/python. Хотел спросить в комментариях, но увы авторизоваться не так то просто, поэтому оформляю статью и прилагаю код. Всё работает, возможно где-то не оптимизировано, т.к. делал аналог РНР-шнго кода. Увы есть проблема, с которой не сложилось. Текст в PIL (Python Imaging Library) вставляется со сглаженными краями, а необходим просто черный по белому без эффектов. Есть идея через промежуточное изображение b/w, но может есть более оригинальный выход. Если да, подскажите, буду рад.
#!/usr/bin/python
## -*- coding: utf-8 -*-
import ImageDraw, PIL, StringIO, string
from PIL import Image, ImageFont
from random import *
from math import *
class Captcha3d:
CHARS = 'WEafRTYIPAGHJKXBNM3479j';
hypot = 5
cimage = None
text = ''
def __init__(self):
#$this->time = microtime(true);
self.generateCode()
self.render()
def imageColorAllocate(self, r,g,b):
hexchars = "0123456789ABCDEF"
hexcolor = hexchars[r / 16] + hexchars[r % 16] + hexchars[g / 16] + hexchars[g % 16] + hexchars[b / 16] + hexchars[b % 16]
return int(hexcolor, 16)
def generateCode(self):
chars = self.CHARS;
self.text = "".join(choice(chars) for x in range(randint(3, 3)))
def getText(self):
return self.text
def getProection(self, x1,y1,z1):
x = x1 * self.hypot
y = z1 * self.hypot
z = -y1 * self.hypot
xx = 0.707106781187
xy = 0
xz = -0.707106781187
yx = 0.408248290464
yy = 0.816496580928
yz = 0.408248290464 # 1/sqrt(6)
cx = xx*x + xy*y + xz*z
cy = yx*x + yy*y + yz*z + 20*self.hypot
return [cx, cy]
def zFunction(self, x,y):
z = 2.6
if self.cimage.getpixel((y/2,x/2)) == (0,0,0):
z = 0
if z != 0:
z += float(randint(0,60))/100
z += 1.4 * sin((x+self.startX)*pi/15) * sin((y+self.startY)*pi/15)
return z
def render(self):
xx = 30
yy = 60
fontSans = ImageFont.truetype('FreeSans.ttf', 16)
self.cimage = Image.new("RGB", (yy * self.hypot, xx * self.hypot), (255,255,255))
draw = ImageDraw.Draw(self.cimage)
whiteColor = (255,255,255)
draw.rectangle([0, 0, yy * self.hypot, xx * self.hypot], fill=whiteColor)
textColor = (0,0,0)
#imgtext = Image.open("i8n.png")
#self.cimage.paste(imgtext, (0,0))
draw.text((2,0), self.text, font=fontSans, fill=textColor)
self.startX = randint(0,xx)
self.startY = randint(0,yy)
crd = {}
x = 0
while x < (xx+1):
y = 0
while y < (yy+1):
crd[str(x) + '&' + str(y)] = self.getProection(x,y,self.zFunction(x,y))
y += 1
x += 1
x = 0
while x < xx:
y = 0
while y < yy:
coord = []
coord.append((int(crd[str(x) + '&' + str(y)][0]),int(crd[str(x) + '&' + str(y)][1])))
coord.append((int(crd[str(x+1) + '&' + str(y)][0]),int(crd[str(x+1) + '&' + str(y)][1])))
coord.append((int(crd[str(x+1) + '&' + str(y+1)][0]),int(crd[str(x+1) + '&' + str(y+1)][1])))
coord.append((int(crd[str(x) + '&' + str(y+1)][0]),int(crd[str(x) + '&' + str(y+1)][1])))
c = int(self.zFunction(x,y)*32)
linesColor = (c,c,c)
draw.polygon(coord, fill=whiteColor, outline=linesColor)
#draw.polygon(coord, fill=whiteColor)
y += 1
x += 1
#draw.text((2,0), self.text, font=fontSans, fill=textColor)
#imageString($this->image, 1, 3, 0, (microtime(true)-$this->time), $textColor);
del draw
self.cimage.save("image.png", "PNG")
#return self.cimage
def main():
a = Captcha3d()
print a.getText()
if __name__ == '__main__':
main()