Example #1
0
    def extract_VOP(self, page, rotatefunc, scale, choice):
        """Extract statistics for a single oval or writein from the ballot.

        """
        iround = lambda x: int(round(x))
        adj = lambda f: int(round(const.dpi * f))
        x, y = choice.coords()
        x = int(x)
        y = int(y)

        # NO horizontal margins in crop - grabbing region between marks!
        # const.margin_width_inches not used
        # hotspot_x_offset_inches IS used
        scaled_page_offset_x = page.xoff / scale
        scaled_page_offset_y = page.yoff / scale
        self.log.debug("Incoming coords (%d,%d), \
page offsets (%d,%d) template offsets (%d,%d)" %
                       (x, y, page.xoff, page.yoff, scaled_page_offset_x,
                        scaled_page_offset_y))
        # adjust x and y for the shift of landmark between template and ballot
        x = iround(x + scaled_page_offset_x - page.template.xoff)
        y = iround(y + scaled_page_offset_y - page.template.yoff)
        self.log.debug("Result of transform: (%d,%d)" % (x, y))

        x, y = rotatefunc(x, y, scale)
        cropx = x
        cropy = y
        cropy -= adj(.1)

        # NO horizontal margins in crop - grabbing region between marks!
        croplist = (cropx + self.hotspot_x_offset_inches,
                    cropy - page.margin_height,
                    min(
                        cropx + self.hotspot_x_offset_inches +
                        page.target_width, page.image.size[0] - 1),
                    min(cropy + page.margin_height + page.target_height,
                        page.image.size[1] - 1))
        crop = page.image.crop(croplist)
        cropstat = ImageStat.Stat(crop)
        stats = Ballot.IStats(cropstats(crop, cropx, cropy))
        #can be in separate func?

        voted, ambiguous = self.extensions.IsVoted(crop, stats, choice)
        writein = False
        if voted:
            # extension is overriden with local function for this ballot type
            writein = IsWriteIn(crop, stats, choice)
            if writein:
                x1 = min(self.writein_xoff + cropx, cropx)
                x2 = max(self.writein_xoff + cropx, cropx)
                y1 = min(self.writein_yoff + cropy, cropy + adj(.2))
                y2 = max(self.writein_yoff + cropy, cropy + adj(.2))
                crop = page.image.crop((x1, y1 - page.margin_height,
                                        min(x2, page.image.size[0] - 1),
                                        min(y2 + page.margin_height,
                                            page.image.size[1] - 1)))
        return cropx, cropy, stats, crop, voted, writein, ambiguous
Example #2
0
 def do(color, box, v, a):
     i = Image.new("RGB", (100, 100), "#fff")
     d = ImageDraw.Draw(i)
     d.rectangle((20, 20, 80, 80), fill="#000")
     d.rectangle(carve, fill="#fff")
     d.rectangle(box, fill=("#" + color*3))
     s = Ballot.IStats(i.cropstats(100, 5, 20, 20, 60, 60, 1))
     vp, ap = Ballot.IsVoted(i, s, None)
     assert vp == v and ap == a
Example #3
0
    def extract_VOP(self, page, rotatefunc, scale, choice):
        """Extract a single oval, or writein box, from the specified ballot"""
        iround = lambda x: int(round(x))
        x, y = choice.coords()
        printed_oval_height = adj(const.target_height_inches)

        #BEGIN SHARABLE
        scaled_page_offset_x = page.xoff / scale
        scaled_page_offset_y = page.yoff / scale
        self.log.debug(
            "Incoming coords (%d,%d), \
page offsets (%d,%d) scaled page offsets (%d,%d), template offsets (%d,%d)" %
            (x, y, page.xoff, page.yoff, scaled_page_offset_x,
             scaled_page_offset_y, page.template.xoff, page.template.yoff))
        # adjust x and y for the shift of landmark between template and ballot
        x = iround(x + scaled_page_offset_x - page.template.xoff)
        y = iround(y + scaled_page_offset_y - page.template.yoff)
        self.log.debug("Result of translation: (%d,%d)" % (x, y))

        x, y = rotatefunc(x, y, scale)
        self.log.debug("Result of rotation: (%d,%d)" % (x, y))
        # Below is using the pure python cropstats:
        cropx, cropy = x, y  #not adjusted like in PILB cropstats

        crop = page.image.crop(
            (cropx - page.margin_width, cropy - page.margin_height,
             min(cropx + page.margin_width + page.target_width,
                 page.image.size[0] - 1),
             min(cropy + page.margin_height + page.target_height,
                 page.image.size[1] - 1)))
        stats = Ballot.IStats(cropstats(crop, x, y))

        voted, ambiguous = self.extensions.IsVoted(crop, stats, choice)
        writein = self.extensions.IsWriteIn(crop, stats, choice)
        if writein:
            crop = page.image.crop(
                (cropx - page.margin_width + self.writein_xoff,
                 cropy - page.margin_height + self.writein_yoff,
                 min(cropx + page.margin_width + self.writein_width,
                     page.image.size[0] - 1),
                 min(cropy + page.margin_height + self.writein_height,
                     page.image.size[1] - 1)))

        return cropx, cropy, stats, crop, voted, writein, ambiguous
Example #4
0
    def extract_VOP(self, page, rotatefunc, scale, choice):
        """Extract a single oval, or writein box, from the specified ballot"""
        iround = lambda x: int(round(x))
        adj = lambda a: int(round(const.dpi * a))
        x, y = choice.coords()
        margin_width = page.margin_width
        margin_height = page.margin_height
        printed_oval_height = adj(0.097)

        #BEGIN SHARABLE
        scaled_page_offset_x = page.xoff / scale
        scaled_page_offset_y = page.yoff / scale
        self.log.debug("Incoming coords (%d,%d), \
page offsets (%d,%d) template offsets (%d,%d)" %
                       (x, y, page.xoff, page.yoff, scaled_page_offset_x,
                        scaled_page_offset_y))
        # adjust x and y for the shift of landmark between template and ballot
        x = iround(x + scaled_page_offset_x - page.template.xoff)
        y = iround(y + scaled_page_offset_y - page.template.yoff)
        self.log.debug("Result of transform: (%d,%d)" % (x, y))

        x, y = rotatefunc(x, y, scale)
        #END SHARABLE
        cropx, cropy = x, y  #not adjusted like in PILB cropstats
        crop = page.image.crop(
            (cropx - page.margin_width, cropy - page.margin_height,
             min(cropx + page.margin_width + page.target_width,
                 page.image.size[0] - 1),
             min(cropy + page.margin_height + page.target_height,
                 page.image.size[1] - 1)))

        # check strip at center to look for either filled or empty oval;
        # recenter vertically
        stripe = crop.crop(
            ((crop.size[0] / 2), 0, (crop.size[0] / 2) + 1, crop.size[1] - 1))
        before_oval = 0
        after_oval = 0
        oval = 0
        stripedata = list(stripe.getdata())
        for num, p in enumerate(stripedata):
            if p[0] > 245:
                before_oval += 1
            else:
                try:
                    if ((stripedata[before_oval + printed_oval_height - 2][0] <
                         245) or (stripedata[before_oval +
                                             printed_oval_height - 1][0] < 245)
                            or (stripedata[before_oval +
                                           printed_oval_height][0] < 245) or
                        (stripedata[before_oval + printed_oval_height + 1][0] <
                         245) or
                        (stripedata[before_oval + printed_oval_height + 2][0] <
                         245)):
                        oval_start = num
                        oval_end = num + printed_oval_height
                        after_oval = stripe.size[1] - (oval_start +
                                                       printed_oval_height)
                        break
                except IndexError:
                    break
        #print cropy,before_oval,oval,after_oval
        afterlessbefore = int(round((after_oval - before_oval) / 2))
        if abs(afterlessbefore) > 2:
            cropy -= afterlessbefore
            #print "Adjusted",cropy
            crop = page.image.crop(
                (cropx - page.margin_width, cropy - page.margin_height,
                 min(cropx + page.margin_width + page.target_width,
                     page.image.size[0] - 1),
                 min(cropy + page.margin_height + page.target_height,
                     page.image.size[1] - 1)))
        stats = Ballot.IStats(cropstats(crop, x, y))

        voted, ambiguous = self.extensions.IsVoted(crop, stats, choice)
        writein = self.extensions.IsWriteIn(crop, stats, choice)
        if writein:
            crop = page.image.crop(
                (cropx - page.margin_width, cropy - page.margin_height,
                 min(cropx + page.margin_width + self.writein_xoff,
                     page.image.size[0] - 1),
                 min(cropy + page.margin_height + self.writein_yoff,
                     page.image.size[1] - 1)))

        return cropx, cropy, stats, crop, voted, writein, ambiguous
Example #5
0
    def extract_VOP(self, page, rotatefunc, scale, choice):
        """Extract a single oval, or writein box, from the specified ballot"""
        iround = lambda x: int(round(x))
        x, y = choice.coords()
        printed_oval_height = adj(const.target_height_inches)

        #BEGIN SHARABLE
        scaled_page_offset_x = page.xoff / scale
        scaled_page_offset_y = page.yoff / scale
        self.log.debug(
            "Incoming coords (%d,%d), \
page offsets (%d,%d) scaled page offsets (%d,%d), template offsets (%d,%d)" %
            (x, y, page.xoff, page.yoff, scaled_page_offset_x,
             scaled_page_offset_y, page.template.xoff, page.template.yoff))
        # adjust x and y for the shift of landmark between template and ballot
        x = iround(x + scaled_page_offset_x - page.template.xoff)
        y = iround(y + scaled_page_offset_y - page.template.yoff)
        self.log.debug("Result of translation: (%d,%d)" % (x, y))

        x, y = rotatefunc(x, y, scale)
        self.log.debug("Result of rotation: (%d,%d)" % (x, y))
        # Below is using the pure python cropstats:
        cropx, cropy = x, y  #not adjusted like in PILB cropstats

        crop = page.image.crop(
            (cropx - page.margin_width, cropy - page.margin_height,
             min(cropx + page.margin_width + page.target_width,
                 page.image.size[0] - 1),
             min(cropy + page.margin_height + page.target_height,
                 page.image.size[1] - 1)))

        # Commenting out material below as regardless of adding or subtracting
        # based upon it, it makes things worse in some situations (?)
        # The rotation is working well to capture the correct area.
        """
        # check strip at center to look for either filled or empty oval;
        # recenter vertically

        stripe = crop.crop(((crop.size[0]/2),0,(crop.size[0]/2)+1,crop.size[1]-1))
        before_oval = 0
        after_oval = 0
        oval = 0
        dark_threshold = 192
        stripedata = list(stripe.getdata())
        for num,p in enumerate(stripedata):
            if p[0] > dark_threshold:
                before_oval += 1
            else:
                try:
                    if ((stripedata[before_oval+printed_oval_height-2][0] < dark_threshold) or 
                        (stripedata[before_oval+printed_oval_height-1][0] < dark_threshold) or 
                        (stripedata[before_oval+printed_oval_height][0] < dark_threshold) or
                        (stripedata[before_oval+printed_oval_height+1][0] < dark_threshold) or
                        (stripedata[before_oval+printed_oval_height+2][0] < dark_threshold)):
                        oval_start = num
                        ov_end = num + printed_oval_height
                        after_oval = stripe.size[1] - (oval_start+printed_oval_height)
                        break
                except IndexError:
                    break
        afterlessbefore = int(round((after_oval - before_oval)/2))
        if abs(afterlessbefore)>2:
            cropy += afterlessbefore
            self.log.debug("Result of afterlessbefore %d: (%d,%d)" % (
                    afterlessbefore,x,cropy))
            crop = page.image.crop((
                cropx - page.margin_width,
                cropy - page.margin_height,
                min(cropx + page.margin_width + page.target_width,
                    page.image.size[0]-1),
                min(cropy + page.margin_height + page.target_height,
                    page.image.size[1]-1)
                ))
        """
        stats = Ballot.IStats(cropstats(crop, x, y))

        voted, ambiguous = self.extensions.IsVoted(crop, stats, choice)
        writein = self.extensions.IsWriteIn(crop, stats, choice)
        if writein:
            crop = page.image.crop(
                (cropx - page.margin_width + self.writein_xoff,
                 cropy - page.margin_height + self.writein_yoff,
                 min(cropx + page.margin_width + self.writein_width,
                     page.image.size[0] - 1),
                 min(cropy + page.margin_height + self.writein_height,
                     page.image.size[1] - 1)))

        return cropx, cropy, stats, crop, voted, writein, ambiguous
Example #6
0
    def extract_VOP(self, page, rotatefunc, scale, choice):
        """Extract a single oval, or writein box, from the specified ballot.
        We'll tell you the coordinates, you tell us the stats.  The
        information gathered should enable the IsVoted function to 
        make a reasonable decision about whether the area was voted,
        but the data is also available to anyone else wanting to see
        the raw statistics to make their own decision.
        """
        print "In extract_VOP"
        adj = lambda f: int(round(const.dpi * f))
        iround = lambda x: int(round(x))
        # choice coords should be the upper left hand corner 
        # of the bounding box of the printed vote target
        adj = lambda f: int(round(const.dpi * f))
        x, y = choice.coords()
        x = int(x)
        y = int(y)
        margin_width = page.margin_width
        margin_height = page.margin_height

        scaled_page_offset_x = page.xoff/scale
        scaled_page_offset_y = page.yoff/scale
        self.log.debug("Incoming coords (%d,%d), \
page offsets (%d,%d) template offsets (%d,%d)" % (
                x,y,
                page.xoff,page.yoff,
                scaled_page_offset_x,scaled_page_offset_y))
        # adjust x and y for the shift of landmark between template and ballot
        x = iround(x + scaled_page_offset_x - page.template.xoff)
        y = iround(y + scaled_page_offset_y - page.template.yoff)
        self.log.debug("Result of transform: (%d,%d)" % (x,y))
        
        x, y = rotatefunc(x, y, scale)

        ow, oh = page.target_width,page.target_height

        print """At %d dpi, on a scale of 0 to 255, 
tell us the average intensity from (%d, %d) for width %d height %d, 
given an offset from the specified x of %d
""" % (const.dpi, x, y, ow, oh, self.vote_target_horiz_offset)
        intensity = ask("Intensity", IntIn(0, 255))
        lowest = ask("Lowest count", IntIn(0, 1000))
        low = ask("Low count", IntIn(0, 1000))
        high = ask("High count", IntIn(0, 1000))
        highest = ask("Highest count", IntIn(0, 1000))
        suspicious = ask("Value of suspicious", int)
        ari, agi, abi  = intensity, intensity, intensity
        lowestr, lowestg, lowestb = lowest, lowest, lowest
        lowr, lowg, lowb = low, low, low
        highestr, highestg, highestb = highest, highest, highest
        highr, highg, highb = high, high, high
        stats = Ballot.IStats(
(ari, lowestr, lowr, highr, highestr,
agi, lowestg, lowg, highg, highestg,
abi, lowestb, lowb, highb, highestb, x, y, 0)
        )

        #can be in separate func?
        cropx = stats.adjusted.x
        cropy = stats.adjusted.y
        crop = page.image.crop((
            cropx - margin_width,
            cropy - margin_height,
            cropx + margin_width + ow, 
            cropy + margin_height + oh
        ))

        #can be in separate func?
        
        voted, ambiguous = self.extensions.IsVoted(crop, stats, choice)
        writein = False
        if voted:
           writein = self.extensions.IsWriteIn(crop, stats, choice)
        if writein:
            print "Gather information about the write-in at",
            print cropx - margin_width, cropy - margin_height,
            print cropx + self.writein_xoff + margin_width,
            print cropy + self.writein_yoff + margin_height

        return cropx, cropy, stats, crop, voted, writein, ambiguous
Example #7
0
    def extract_VOP(self, page, rotatefunc, scale, choice):
        """Extract a single oval, or writein box, from the specified ballot.
        
        Note that cropstats is C code in Imaging-1.1.7, most of which 
        fine-tunes the location of a Hart ballot vote box. The fine-tuning
        is left OFF in this call to cropstats.

        The "suspicious" value returned from cropstats is toggled if
        there is any dark pixel in the central region of the oval; this
        may be more appropriate to rectangular vote ops as in Hart.

        The IStats class in Ballot provides more convenient access
        to the list of information returned from cropstats.

        The determination of whether a vote target was actually voted,
        or whether a vote target represents a write-in, is currently
        performed by the default functions set into the Ballot Extensions
        object.  These functions may be overriden. XXX Example!
        """
        adj = lambda f: int(round(const.dpi * f))
        iround = lambda x: int(round(x))
        x, y = choice.coords()
        x = int(x)
        y = int(y)
        margin_width = page.margin_width
        margin_height = page.margin_height

        #BEGIN SHARABLE
        scaled_page_offset_x = page.xoff / scale
        scaled_page_offset_y = page.yoff / scale
        self.log.debug("Incoming coords (%d,%d), \
page offsets (%d,%d) template offsets (%d,%d)" %
                       (x, y, page.xoff, page.yoff, scaled_page_offset_x,
                        scaled_page_offset_y))
        # adjust x and y for the shift of landmark between template and ballot
        x = iround(x + scaled_page_offset_x - page.template.xoff)
        y = iround(y + scaled_page_offset_y - page.template.yoff)
        self.log.debug("Result of transform: (%d,%d)" % (x, y))

        x, y = rotatefunc(x, y, scale)
        #END SHARABLE
        ow = page.target_width
        oh = page.target_height

        stats = Ballot.IStats(
            page.image.cropstats(
                const.dpi,
                self.vote_target_horiz_offset,
                x,
                y,
                ow,
                oh,
                0  # NOTE, this turns OFF fine adjustment, tuned to Hart in Imaging
            ))

        #can be in separate func?
        cropx = stats.adjusted.x
        cropy = stats.adjusted.y
        crop = page.image.crop(
            (cropx - margin_width, cropy - margin_height,
             cropx + margin_width + ow, cropy + margin_height + oh))

        #can be in separate func?
        voted, ambiguous = self.extensions.IsVoted(crop, stats, choice)
        writein = False
        if voted:
            writein = self.extensions.IsWriteIn(crop, stats, choice)
        if writein:
            crop = page.image.crop(
                (cropx - margin_width, cropy - margin_height,
                 min(cropx + self.writein_xoff + margin_width,
                     page.image.size[0] - 1),
                 min(cropy + self.writein_yoff + margin_height,
                     page.image.size[1] - 1)))

        return cropx, cropy, stats, crop, voted, writein, ambiguous