Beispiel #1
0
 def __init__(self,
              image,
              background,
              dpi,
              precision=16,
              deskew=True,
              contrast=10):
     self.contrast = contrast
     self.image = image
     self.dpi = dpi
     self.width, self.height = image.size
     self.precision = precision
     self.deskew = deskew
     self.samples = PixelSampler(image, dpi, precision)
     self.background = background
     self.sections = self._find_sections()
Beispiel #2
0
class MultiPartImage(object):
    """Object for handling images that contain multiple subimages.
    
    This is used, for example, to detect and access multiple photos that were
    scanned simultaneously in a flat-bed scanner. """

    def __init__(self, image, background, dpi, precision=16, deskew=True, contrast=10):
        self.contrast = contrast
        self.image = image
        self.dpi = dpi
        self.width, self.height = image.size
        self.precision = precision
        self.deskew = deskew
        self.samples = PixelSampler(image, dpi, precision)
        self.background = background
        self.sections = self._find_sections()

    def __iter__(self):
        for section in self.sections:
            image = self.image.crop((section.left, section.top, section.right, section.bottom))
            if self.deskew:
                skew = SkewedImage(image, self.background, self.contrast)
                image = skew.correct()
            yield image

    def __len__(self):
        return len(self.sections)

    def _find_sections(self):
        sections = []
        for (x, y, red, green, blue) in self.samples:
            # Skip if the sample is background or is already in a section.
            if self.background.matches(red, green, blue, self.contrast):
                continue
            if True in (section.contains(x, y) for section in sections):
                continue

            # Find contiguous samples. This works like a 4-way flood fill, but
            # instead of changing the color we just collect the coordinates.
            seeds = [(x, y)]
            pixels = set(seeds)
            for coords in iter(seeds):
                for x, y, r, g, b in self.samples.around(*coords):
                    if (x, y) not in pixels:
                        pixels.add((x, y))
                        if not self.background.matches(r, g, b, self.contrast):
                            seeds.append((x, y))
            new_section = ImageSection(pixels)

            if True in (s.merge_if_overlapping(new_section) for s in sections):
                continue

            sections.append(new_section)

        # Filter out sections smaller than 1 square inch before returning.
        return [s for s in sections if s > self.dpi ** 2]
Beispiel #3
0
 def __init__(self, image, background, dpi, precision=16, deskew=True, contrast=10):
     self.contrast = contrast
     self.image = image
     self.dpi = dpi
     self.width, self.height = image.size
     self.precision = precision
     self.deskew = deskew
     self.samples = PixelSampler(image, dpi, precision)
     self.background = background
     self.sections = self._find_sections()
Beispiel #4
0
 def __init__(self, image, background, contrast=10):
     self.image = image
     self.width, self.height = image.size
     self.background = background
     self.contrast = contrast
     sampler = PixelSampler(image, dpi=1, precision=1)
     self.sides = (
         Left(sampler),
         Top(sampler),
         Right(sampler),
         Bottom(sampler),
         )
Beispiel #5
0
 def load_from_image(self, image, dpi):
     """Determine background stats by examining a blank scan.
     """
     sampler = PixelSampler(image, dpi, precision=4)
     reds, greens, blues = zip(*[sample[2:] for sample in sampler])
     self.medians = {
         'red': numpy.median(reds),
         'green': numpy.median(greens),
         'blue': numpy.median(blues),
         }
     self.std_devs = {
         'red': numpy.std(reds),
         'green': numpy.std(greens),
         'blue': numpy.std(blues),
         }
     return self
Beispiel #6
0
class MultiPartImage(object):
    """Object for handling images that contain multiple subimages.
    
    This is used, for example, to detect and access multiple photos that were
    scanned simultaneously in a flat-bed scanner. """
    def __init__(self,
                 image,
                 background,
                 dpi,
                 precision=16,
                 deskew=True,
                 contrast=10):
        self.contrast = contrast
        self.image = image
        self.dpi = dpi
        self.width, self.height = image.size
        self.precision = precision
        self.deskew = deskew
        self.samples = PixelSampler(image, dpi, precision)
        self.background = background
        self.sections = self._find_sections()

    def __iter__(self):
        for section in self.sections:
            image = self.image.crop(
                (section.left, section.top, section.right, section.bottom))
            if self.deskew:
                skew = SkewedImage(image, self.background, self.contrast)
                image = skew.correct()
            yield image

    def __len__(self):
        return len(self.sections)

    def _find_sections(self):
        sections = []
        for (x, y, red, green, blue) in self.samples:
            # Skip if the sample is background or is already in a section.
            if self.background.matches(red, green, blue, self.contrast):
                continue
            if True in (section.contains(x, y) for section in sections):
                continue

            # Find contiguous samples. This works like a 4-way flood fill, but
            # instead of changing the color we just collect the coordinates.
            seeds = [(x, y)]
            pixels = set(seeds)
            for coords in iter(seeds):
                for x, y, r, g, b in self.samples.around(*coords):
                    if (x, y) not in pixels:
                        pixels.add((x, y))
                        if not self.background.matches(r, g, b, self.contrast):
                            seeds.append((x, y))
            new_section = ImageSection(pixels)

            if True in (s.merge_if_overlapping(new_section) for s in sections):
                continue

            sections.append(new_section)

        # Filter out sections smaller than 1 square inch before returning.
        return [s for s in sections if s > self.dpi**2]