File: imageManipulation.py

package info (click to toggle)
ocrfeeder 0.6.6%2Bdfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 1,616 kB
  • ctags: 2,088
  • sloc: python: 16,603; makefile: 52
file content (146 lines) | stat: -rw-r--r-- 5,198 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# -*- coding: utf-8 -*-

###########################################################################
#    OCRFeeder - The complete OCR suite
#    Copyright (C) 2009 Joaquim Rocha
# 
#    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 tempfile
from ocrfeeder.util.lib import debug

import gettext
import Image, ImageDraw
import os.path
from ocrfeeder.util import graphics
import sys

_ = gettext.gettext

class ImageProcessor:
    
    def __init__(self, path_to_image, window_size = None):
        self.window_size = window_size
        error_message = _("A problem occurred while trying to open the image:\n %s\n"
                          "Ensure the image exists or try converting it to another format.") % path_to_image
        if os.path.isfile(path_to_image):
            try:
                self.original_image = Image.open(path_to_image)
                self.black_n_white_image = self.original_image.convert('L')
                if not self.window_size:
                    self.window_size = self.original_image.size[1] / 60.
                debug('Window Size: ', self.window_size)
            except:
                debug(sys.exc_info())
                raise ImageManipulationError(error_message)
        else:
            debug(sys.exc_info())
            raise ImageManipulationError(error_message)
            
    def __windowContrast(self, bgcolor, x, y, constrast_tolerance = 120):
        image = self.black_n_white_image
        width, height = image.size
        
        image_upper_left_corner_x = x * self.window_size
        image_upper_left_corner_y = y * self.window_size
        
        i, j = 1, 1
        while j < self.window_size + 1:
            if not image_upper_left_corner_y + j < height:
                break
            while i < self.window_size + 1:
                if not image_upper_left_corner_x + i < width:
                    break
                if graphics.colorsContrast(image.getpixel((image_upper_left_corner_x + i, image_upper_left_corner_y + j)), bgcolor, constrast_tolerance):
                    return 1
                i += 3
            i = 1
            j += 3
        return 0
    
    def imageToBinary(self):
        image = self.black_n_white_image
        binary_info = ['']
        width, height = image.size
        i, j = 0, 0
        while j < height / self.window_size:
            while i < width / self.window_size:
                binary_info[-1] += str(self.__windowContrast(255, i, j))
                i += 1
            i = 0
            binary_info += ['']
            j += 1
        return binary_info

class Slicer:
    
    def __init__(self, original_image, temp_dir = '/tmp'):
        self.original_image = original_image
        self.temp_dir = temp_dir
    
    def slice(self, bounding_box):
        return self.original_image.crop(bounding_box)
    
    def sliceFromPointsList(self, points_list):
        if len(points_list) < 3:
            raise InsuficientPointsForPolygon
        bounding_box = graphics.getContainerRectangle(points_list)
        return self.original_image.crop(bounding_box)
    
    def sliceFromBlock(self, block, window_size):
        cropped_image = self.slice(block.translateToUnits(window_size))
        image_file = tempfile.mkstemp(dir = self.temp_dir)[1]
        cropped_image.save(image_file, format = 'PNG')

class ContentAnalyser:
    
    def __init__(self, image):
        self.image = image
    
    def getHeight(self):
        width, height = self.image.size
        image_draw = ImageDraw.Draw(self.image)
        i = 0
        while i+3 < height:
            current_line_image = self.image.crop((0, i, width, i + 3))
            if len(current_line_image.getcolors()) < 10:
                image_draw.rectangle((0, i, width, i + 3), fill = (255, 255, 255))
            i += 3
        
    def __getBlankSpaceFromTopToBottom(self, image):
        width, height = image.size
        i = 0
        while i + 2 < height:
            current_line_image = image.crop((0, i, width, i + 1))
            if len(current_line_image.getcolors()) > 1:
                break
            i += 2
        return i

class ImageManipulationError(Exception):
    
    def __init__(self, value):
        self.value = value
    
    def __str__(self):
        return self.value
    
class InsuficientPointsForPolygon(Exception):
    
    def __init__(self):
        pass
    
    def __str__(self):
        return 'Insufficient number of points for polygon. Must be at least three points.'