diff options
Diffstat (limited to 'module')
| -rw-r--r-- | module/captcha/GigasizeCom.py | 15 | ||||
| -rw-r--r-- | module/captcha/MegauploadCom.py | 14 | ||||
| -rw-r--r-- | module/captcha/NetloadIn.py | 25 | ||||
| -rw-r--r-- | module/captcha/ShareonlineBiz.py | 61 | ||||
| -rw-r--r-- | module/captcha/__init__.py | 0 | ||||
| -rw-r--r-- | module/captcha/captcha.py | 292 | 
6 files changed, 407 insertions, 0 deletions
diff --git a/module/captcha/GigasizeCom.py b/module/captcha/GigasizeCom.py new file mode 100644 index 000000000..136092181 --- /dev/null +++ b/module/captcha/GigasizeCom.py @@ -0,0 +1,15 @@ +from captcha import OCR + +class GigasizeCom(OCR): +    def __init__(self): +        OCR.__init__(self) +         +    def get_captcha(self, image): +        self.load_image(image) +        self.threshold(2.8) +        self.run_gocr() +        return self.result_captcha + +if __name__ == '__main__': +    ocr = GigasizeCom() +    print  ocr.get_captcha('gigasize-com/7.jpg') diff --git a/module/captcha/MegauploadCom.py b/module/captcha/MegauploadCom.py new file mode 100644 index 000000000..40939c792 --- /dev/null +++ b/module/captcha/MegauploadCom.py @@ -0,0 +1,14 @@ +from captcha import OCR + +class MegauploadCom(OCR): +    def __init__(self): +        OCR.__init__(self) +         +    def get_captcha(self, image): +        self.load_image(image) +        self.threshold(2.8) +        self.run_tesser() +        return self.result_captcha + +if __name__ == '__main__': +    ocr = MegauploadCom() diff --git a/module/captcha/NetloadIn.py b/module/captcha/NetloadIn.py new file mode 100644 index 000000000..9799a6a2b --- /dev/null +++ b/module/captcha/NetloadIn.py @@ -0,0 +1,25 @@ +from captcha import OCR + +class NetloadIn(OCR): +    def __init__(self): +        OCR.__init__(self) + +    def get_captcha(self, image): +        self.load_image(image) +        self.to_greyscale() +        self.clean(3) +        self.clean(3) +        self.run_tesser() + +        self.correct({ +        ("$", "g"): "5", +        }) + +        return self.result_captcha + +if __name__ == '__main__': +    import urllib +    ocr = NetloadIn() +    urllib.urlretrieve("http://netload.in/share/includes/captcha.php", "captcha.png") + +    print  ocr.get_captcha('captcha.png') diff --git a/module/captcha/ShareonlineBiz.py b/module/captcha/ShareonlineBiz.py new file mode 100644 index 000000000..91124f181 --- /dev/null +++ b/module/captcha/ShareonlineBiz.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +#Copyright (C) 2009 kingzero, RaNaN +# +#This program is free software; you can redistribute it and/or modify +#it under the terms of the GNU General Public License as published by +#the Free Software Foundation; either version 3 of the License, +#or (at your option) any later version. +# +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +#See the GNU General Public License for more details. +# +#You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +### +from captcha import OCR + +class ShareonlineBiz(OCR): +    def __init__(self): +        OCR.__init__(self) +         +    def get_captcha(self, image):  +        self.load_image(image) +        self.to_greyscale() +        self.image = self.image.resize((160, 50)) +        self.pixels = self.image.load() +        self.threshold(1.85) +        #self.eval_black_white(240) +        #self.derotate_by_average() + +        letters = self.split_captcha_letters() +         +        final = "" +        for letter in letters: +            self.image = letter +            self.run_tesser() +            final += self.result_captcha + +        #replace common errors +        final = self.correct({ +        "A": "4", +        "‘5": "3", +        ("‘1", "T"): "7", +        ("‘L", "B", "'L"): "2", +        "b": "6", +        ("I", "X"): "1" +        }, final) + +        return final + +        #tesseract at 60% + +if __name__ == '__main__': +    import urllib +    ocr = ShareonlineBiz() +    urllib.urlretrieve("http://www.share-online.biz/captcha.php", "captcha.jpeg") +    print  ocr.get_captcha('captcha.jpeg') diff --git a/module/captcha/__init__.py b/module/captcha/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/module/captcha/__init__.py diff --git a/module/captcha/captcha.py b/module/captcha/captcha.py new file mode 100644 index 000000000..ffb165dbf --- /dev/null +++ b/module/captcha/captcha.py @@ -0,0 +1,292 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +#Copyright (C) 2009 kingzero, RaNaN +# +#This program is free software; you can redistribute it and/or modify +#it under the terms of the GNU General Public License as published by +#the Free Software Foundation; either version 3 of the License, +#or (at your option) any later version. +# +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +#See the GNU General Public License for more details. +# +#You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +### +import logging +import subprocess +import tempfile +import threading + +import Image + +class RunThread(threading.Thread): +    def __init__(self): +        threading.Thread.__init__(self) + +    def e(self, command, inputdata=None): +        """execute command """ +        self.command = command +        self.inputdata = inputdata +        self.result = "" +        self.start() +        self.join(10) +        return self.result + +    def run(self): +        """Run a command and return standard output""" +        pipe = subprocess.PIPE +        popen = subprocess.Popen(self.command, stdout=pipe, stderr=pipe) +        outputdata, errdata = popen.communicate(self.inputdata) +        assert (popen.returncode == 0), \ +            "Error running: %s\n\n%s" % (self.command, errdata) +        self.result = outputdata + +class OCR(object): +    def __init__(self): +        self.logger = logging.getLogger("log") + +    def load_image(self, image): +        self.image = Image.open(image) +        self.pixels = self.image.load() +        self.result_captcha = '' + +    def unload(self): +        """delete all tmp images""" +        pass + +    def threshold(self, value): +        self.image = self.image.point(lambda a: a * value + 10) + +    def run(self, command, inputdata=None): +        """Run a command and return standard output""" +    #        OLD METHOD +    #        pipe = subprocess.PIPE +    #        popen = subprocess.Popen(command, stdout=pipe, stderr=pipe) +    #        outputdata, errdata = popen.communicate(inputdata) +    #        assert (popen.returncode == 0), \ +    #            "Error running: %s\n\n%s" % (command, errdata) +    #        return outputdata + +        thread = RunThread() +        result = thread.e(command, inputdata) +        return result + +    def run_gocr(self): +        tmp = tempfile.NamedTemporaryFile(suffix=".jpg") +        self.image.save(tmp) +        self.result_captcha = self.run(['gocr', tmp.name]).replace("\n", "") + +    def run_tesser(self): +        self.logger.debug("create tmp tif") +        tmp = tempfile.NamedTemporaryFile(suffix=".tif") +        self.logger.debug("create tmp txt") +        tmpTxt = tempfile.NamedTemporaryFile(suffix=".txt") +        self.logger.debug("save tiff") +        self.image.save(tmp.name, 'TIFF') +        self.logger.debug("run tesseract") +        self.run(['tesseract', tmp.name, tmpTxt.name.replace(".txt", "")]) +        self.logger.debug("run cat") +        self.result_captcha = self.run(['cat', tmpTxt.name]).replace("\n", "") + +    def get_captcha(self): +        raise NotImplementedError + +    def to_greyscale(self): +        if self.image.mode != 'L': +            self.image = self.image.convert('L') + +        self.pixels = self.image.load() + +    def eval_black_white(self, limit): +        self.pixels = self.image.load() +        w, h = self.image.size +        for x in xrange(w): +            for y in xrange(h): +                if self.pixels[x, y] > limit: +                    self.pixels[x, y] = 255 +                else: +                    self.pixels[x, y] = 0 + +    def clean(self, allowed): +        pixels = self.pixels + +        w, h = self.image.size + +        for x in xrange(w): +            for y in xrange(h): +                if pixels[x, y] == 255: continue +                # no point in processing white pixels since we only want to remove black pixel +                count = 0 + +                try: +                    if pixels[x-1, y-1] != 255: count += 1 +                    if pixels[x-1, y] != 255: count += 1 +                    if pixels[x-1, y + 1] != 255: count += 1 +                    if pixels[x, y + 1] != 255: count += 1 +                    if pixels[x + 1, y + 1] != 255: count += 1 +                    if pixels[x + 1, y] != 255: count += 1 +                    if pixels[x + 1, y-1] != 255: count += 1 +                    if pixels[x, y-1] != 255: count += 1 +                except: +                    pass + +        # not enough neighbors are dark pixels so mark this pixel +            # to be changed to white +                if count < allowed: +                    pixels[x, y] = 1 + +            # second pass: this time set all 1's to 255 (white) +        for x in xrange(w): +            for y in xrange(h): +                if pixels[x, y] == 1: pixels[x, y] = 255 + +        self.pixels = pixels + +    def derotate_by_average(self): +        """rotate by checking each angle and guess most suitable""" + +        w, h = self.image.size +        pixels = self.pixels + +        for x in xrange(w): +            for y in xrange(h): +                if pixels[x, y] == 0: +                    pixels[x, y] = 155 + +        highest = {} +        counts = {} + +        for angle in range(-45, 45): + +            tmpimage = self.image.rotate(angle) + +            pixels = tmpimage.load() + +            w, h = self.image.size + +            for x in xrange(w): +                for y in xrange(h): +                    if pixels[x, y] == 0: +                        pixels[x, y] = 255 + + +            count = {} + +            for x in xrange(w): +                count[x] = 0 +                for y in xrange(h): +                    if pixels[x, y] == 155: +                        count[x] += 1 + +            sum = 0 +            cnt = 0 + +            for x in count.values(): +                if x != 0: +                    sum += x +                    cnt += 1 + +            avg = sum / cnt +            counts[angle] = cnt +            highest[angle] = 0 +            for x in count.values(): +                if x > highest[angle]: +                    highest[angle] = x + +            highest[angle] = highest[angle] - avg + +        hkey = 0 +        hvalue = 0 + +        for key, value in highest.iteritems(): +            if value > hvalue: +                hkey = key +                hvalue = value + +        self.image = self.image.rotate(hkey) +        pixels = self.image.load() + +        for x in xrange(w): +            for y in xrange(h): +                if pixels[x, y] == 0: +                    pixels[x, y] = 255 + +                if pixels[x, y] == 155: +                    pixels[x, y] = 0 + +        self.pixels = pixels + +    def split_captcha_letters(self): +        captcha = self.image +        started = False +        letters = [] +        width, height = captcha.size +        bottomY, topY = 0, height +        pixels = captcha.load() + +        for x in xrange(width): +            black_pixel_in_col = False +            for y in xrange(height): +                if pixels[x, y] != 255: +                    if started == False: +                        started = True +                        firstX = x +                        lastX = x + +                    if y > bottomY: bottomY = y +                    if y < topY: topY = y +                    if x > lastX: lastX = x + +                    black_pixel_in_col = True + +            if black_pixel_in_col == False and started == True: +                rect = (firstX, topY, lastX, bottomY) +                new_captcha = captcha.crop(rect) + +                w, h = new_captcha.size +                if w > 5 and h > 5: +                    letters.append(new_captcha) + +                started = False +                bottomY, topY = 0, height + +        return letters + +    def correct(self, values, var=None): + +        if var: +            result = var +        else: +            result = self.result_captcha + +        for key, item in values.iteritems(): + +            if key.__class__ == str: +                result = result.replace(key, item) +            else: +                for expr in key: +                    result = result.replace(expr, item) + +        if var: +            return result +        else: +            self.result_captcha = result + + +if __name__ == '__main__': +    ocr = OCR() +    ocr.load_image("B.jpg") +    ocr.to_greyscale() +    ocr.eval_black_white(140) +    ocr.derotate_by_avergage() +    ocr.run_gocr() +    print "GOCR", ocr.result_captcha +    ocr.run_tesser() +    print "Tesseract", ocr.result_captcha +    ocr.image.save("derotated.jpg") +      | 
