Example #1
0
    def segmentize(self, input_img):
        histogram = self.__calculate_histogram(input_img)
        (peaks, bottoms) = find_peaks(histogram, max(histogram) / 8)

        for peak in peaks:
            if between(peak, self.expectations['table']):
                self.ranges['table'] = find_hill(histogram, peak, 0.01)
                break  #stop searching, we want the first peak since that is the highest large object.

        if not 'table' in self.ranges:
            if self.verbose:
                cv.ShowImage("histogram", self.__render_histogram(histogram))
            return None

        self.ranges['objects'] = (1, self.ranges['table'][0] - 1)

        print self.ranges

        if self.verbose:
            cv.ShowImage("histogram", self.__render_histogram(histogram))

        objects_img = create_empty_image((input_img.width, input_img.height))
        cv.SetImageROI(objects_img, cv.GetImageROI(input_img))
        cv.InRangeS(input_img, cv.Scalar(self.ranges['objects'][0]),
                    cv.Scalar(self.ranges['objects'][1]), objects_img)

        table_img = create_empty_image((input_img.width, input_img.height))
        cv.SetImageROI(table_img, cv.GetImageROI(input_img))
        cv.InRangeS(input_img, cv.Scalar(self.ranges['table'][0]),
                    cv.Scalar(self.ranges['table'][1]), table_img)

        return {'objects': objects_img, 'table': table_img}
Example #2
0
    def __draw_verbose(self, bin_img, points):
        seg_img = clone_color_image(bin_img)

        if len(points):
            # an extrapolated line!
            (a, b) = polyfit([p.x if p.x > 0 else 1 for p in points],
                             [p.y for p in points], 1)
            f = lambda x: a * x + b

            (dx, dy, width, height) = cv.GetImageROI(seg_img)

            # draw the line (by drawing points, how inefficient!)
            for x in range(width):
                y = f(x)
                cv.Circle(seg_img, (int(dx + x), int(dy + y)), 2,
                          (0, 0, 255, 0), 2, cv.CV_AA)

    # calculate the color of the points
        for idx, point in enumerate(points):
            if idx == 0 or idx == len(points) - 1:
                setattr(point, "colour", (255, 255, 255, 0))
            else:
                setattr(point, "colour",
                        (point.distance(points[idx - 1]) * 2, 255,
                         point.distance(points[idx + 1]) * 2, 0))

    # draw the individual pionts
        for point in points:
            cv.Circle(seg_img,
                      point.move((dx, dy)).as_cv_point(), 3, point.colour, 2,
                      cv.CV_AA)

        cv.ShowImage("TableDetector", seg_img)
        cv.WaitKey(10)
Example #3
0
    def detect(self, img):
        (dx, dy, width, height) = cv.GetImageROI(img)

        # generate a set of points
        points = [Point(x, height - 1) for x in range(0, width - 1, 5)]

        # move points as far up as possible
        self.__drop_points(points, img)

        points = self.__remove_unmoved_points(points, height - 1)

        # remove points that got stuck in noise
        points = self.__remove_outliers(points, self.outlier_threshold)

        if self.verbose:
            self.__draw_verbose(img, points)

        # if there are no points left (like, shitty image or no table)
        # return nothing
        if len(points) == 0:
            return None

        table = self.__extract_table(points, (width, height))

        if self.verbose:
            print table

        return table
def estimate_ballot_rot(I, Imarkfull, bbs, MAX_THETA=2.0, K=5):
    roi_prev = cv.GetImageROI(I)
    w_markfull, h_markfull = cv.GetSize(Imarkfull)
    theta_tm = None
    for bb in bbs:
        roi_cur = tuple(
            map(lambda x: int(round(x)),
                (roi_prev[0] + bb[0], roi_prev[1] + bb[1], bb[2] - bb[0],
                 bb[3] - bb[1])))
        cv.SetImageROI(I, roi_cur)
        w_cur, h_cur = cv.GetSize(I)

        if DEBUG_SAVEIMGS:
            print_dbg("<><><><> Saving '_Imiddle.png' <><><><>")
            cv.SaveImage("_Imiddle.png", I)
            pdb.set_trace()

        matches = tempmatch.get_tempmatches(
            Imarkfull, [I],
            T=0.9,
            do_smooth=tempmatch.SMOOTH_BOTH_BRD,
            xwinI=5,
            ywinI=5,
            xwinA=5,
            ywinA=5)[0]
        matches = sorted(matches, key=lambda t: t[0])
        if matches:
            xs = np.array([t[0] for t in matches])
            ys = np.array([cv.GetSize(I)[1] - t[1] for t in matches])
            if len(xs) <= 1:
                print_dbg("==== Couldn't find enough marks in '_Imiddle.png'.")
                continue
            # Filter out any obvious outliers
            lonely_idxs = detect_lonely_vals(ys, h_markfull)
            xs = np.delete(xs, lonely_idxs)
            ys = np.delete(ys, lonely_idxs)
            if len(xs) <= 1:
                print_dbg("==== Couldn't find enough marks in '_Imiddle.png'.")
                continue
            # Discovered marks must take up at least K*w_markfull space.
            x_area = max(xs) - min(xs)
            if x_area < (K * w_markfull):
                print_dbg(
                    "==== Marks only took up {0}, too small space.".format(
                        x_area))
            else:
                theta_tm_ = estimate_rotation(xs, ys)
                if abs(theta_tm_) > MAX_THETA:
                    print_dbg(
                        "==== Theta was too large: {0}".format(theta_tm_))
                else:
                    theta_tm = theta_tm_
                    break
        else:
            print_dbg("==== Couldn't find any marks in '_Imiddle.png'.")

    cv.SetImageROI(I, roi_prev)

    return theta_tm
def drawit(I, bbs, imgpath, isflip=False):
    Icolor = cv.LoadImage(imgpath, cv.CV_LOAD_IMAGE_COLOR)
    if isflip:
        cv.Flip(Icolor, Icolor, -1)
    cv.SetImageROI(Icolor, cv.GetImageROI(I))
    for (x1, y1, x2, y2) in bbs:
        cv.Rectangle(Icolor, (x1, y1), (x2, y2), cv.CV_RGB(255, 0, 0))
    print "<><><><> Saving '_Icolor.png' <><><><>"
    cv.SaveImage("_Icolor.png", Icolor)
    pdb.set_trace()
Example #6
0
    def segmentize(self, img):
        '''Extract the depth level that only contains the table, ignoring the
        objects and arms (i.e. as if they are holes in the table)'''

        layers = {}

        for name, (low, high) in self.ranges.iteritems():
            layer = cv.CreateImage((img.width, img.height), cv.IPL_DEPTH_8U, 1)
            cv.SetImageROI(layer, cv.GetImageROI(img))
            cv.InRangeS(img, low, high, layer)
            layers[name] = layer

        return layers
Example #7
0
    def __drop_points(self, points, seg_img):
        (dx, dy, width, height) = cv.GetImageROI(seg_img)
        for point in points:
            for y in range(point.y - 1, 0, -1):
                channel = cv.Get2D(seg_img, dy + y, dx + point.x)
                #prev_channel = cv.Get2D(seg_img, dy + y + 1, dx + point.x)
                #diff = channel[0] - prev_channel[0]
                #if diff > 1:
                #seg_img is binary, so values should be 0 or 255
                if channel[0] > 128:
                    break

                point.y = y
Example #8
0
def is_backside(decodings, mark_locs, I, Izero):
    """ Applies Sequoia-specific knowledge. A backside ballot side has
    the following 'barcode' values (assume right-side-up):
        UpperLeft: "0"
        UpperRight: ""    (Just a black bar)
        LowerLeft: "0"
        LowerRight: "0"

    Note: This doesn't detect empty backsides. Assumes that the decoder
    is 'good enough' such that it will not spuriously return "" or "0"
    for an real front-side barcode. 
    
    Output: 
        bool isBack, bool isFlip
    """
    if decodings[0] == "0" and decodings[1] == "":
        # Possibly up-right backside.
        return True, False
    elif decodings[0] == "0" and decodings[1] == "0":
        return True, True
    # Try to handle if ballot is partially-cutoff.
    _roi = cv.GetImageROI(I)
    cv.ResetImageROI(I)
    w_img, h_img = cv.GetSize(I)
    w_fact, h_fact = 0.19, 0.13
    w_patch, h_patch = int(round(w_img * w_fact)), int(round(h_img * h_fact))
    if decodings[0] == "":
        # LHS is possibly cut-off
        cv.SetImageROI(I, (w_img - w_patch, h_img - h_patch, w_patch, h_patch))
        x1, y1, score = tempmatch.bestmatch(
            Izero, [I], do_smooth=tempmatch.SMOOTH_IMG_BRD)[0]
        cv.SetImageROI(I, _roi)
        if score >= 0.9:
            return True, True if decodings[1] == "" else False
        else:
            # No idea! What? Definitely a strange case...
            print "...Wow, this is unexpected!"
            return False, None
    elif decodings[1] == "" and decodings[0] == "0":
        # RHS is possibly cut-off
        cv.SetImageROI(I, (0, h_img - h_patch, w_patch, h_patch))
        x1, y1, score = tempmatch.bestmatch(
            Izero, [I], do_smooth=tempmatch.SMOOTH_IMG_BRD)[0]
        cv.SetImageROI(I, _roi)
        if score >= 0.9:
            return True, False
        else:
            return True, True
    return False, None
Example #9
0
def mean(img, x, y, size=10):
    oldRoi = cv.GetImageROI(img)

    #make sure roi is within image bounds
    x = min(x, img.width - 1)
    x = max(x, 0)
    y = min(y, img.height - 1)
    y = max(y, 0)

    cv.SetImageROI(img, (x - size / 2, y - size / 2, size, size))
    avg = cv.Avg(img)

    cv.SetImageROI(img, oldRoi)

    return (avg[0] + avg[1] + avg[2]) / 3.0
Example #10
0
 def draw(self, img):
     '''
     Draw this corner on img
     @param img:
     '''
     rect = cv.GetImageROI(img)
     cv.ResetImageROI(img)
     col = (255, 255, 255)
     cv.Line(img, self.prev, self.p, col)
     cv.Line(img, self.p, self.next, col)
     #        cv.Line(img, self.p, add(self.p, rotateVec((30, 0), self.rotation), 1), col)
     cv.Circle(img, self.p, 2, col)
     font = cv.InitFont(cv.CV_FONT_HERSHEY_COMPLEX_SMALL, 0.7, 0.7)
     cv.PutText(img, "(%d,%d)" % self.p, self.p, font, col)
     cv.SetImageROI(img, rect)
Example #11
0
    def find_corners(self):
        '''
        Tries to find corners or to predict them. Return empty list,
        if every corner is found, or list of points in the area which tell where
        to do futher checking
        '''
        time = self.m_d.time
        if time - self.last_seen >= MAX_SEEN:
            return False
        #cv.ResetImageROI(draw_img)
        ncorners = []
        bounds = []
        for c in self.corners:
            db.db_break("find_corners")
            cands = c.get_candidates(self.m_d)
            min = NOT_SIMILLAR
            bestcand = None
            for cand in cands:
                if cand.similarity < min:
                    min = cand.similarity
                    bestcand = cand
            ncorners.append(bestcand)
            bounds.extend(cvrect(cv.GetImageROI(self.m_d.bw_img)))
            if bestcand is None:
                pass

        db.pr([ncorners], "find_corners")
        for cor in ncorners:
            if cor is not None:
                cor.draw(self.m_d.tmp_img)
        if None in ncorners:
            pass
        CP = CornerPredictor(self.corners, time, self.m_d)
        ncorners = CP.predict_corners(ncorners)
        db.pr([ncorners], "new corners")
        if ncorners is not None:
            points = [x.p for x in ncorners]
            correctness = self.code_correctness(points)
            if correctness > REQUIRED_CORRECTNESS:
                self.set_new_position(ncorners)
                return True
            else:
                db.PolyLine(self.m_d.tmp_img, [points], True, (255, 255, 255),
                            "%.2f" % correctness)
        self.m_d.borders.extend(CP.bounds)
        return False
def find_col_x1(I, Icol, bb, K=3, AX=0.2, AY=0.2, T=0.9):
    """ Tries to find the column of marks on I, using ICOL as a ref.
    image in template matching.
    """
    roi_prev = cv.GetImageROI(I)
    shift_roi(I, bb[0], bb[1], bb[2] - bb[0], bb[3] - bb[1])

    w_A, h_A = cv.GetSize(Icol)
    w_I, h_I = cv.GetSize(I)
    M = cv.CreateMat(h_I - h_A + 1, w_I - w_A + 1, cv.CV_32F)
    cv.MatchTemplate(I, Icol, M, cv.CV_TM_CCOEFF_NORMED)
    if DEBUG_SAVEIMGS:
        M_np = np.array(M)
        import scipy.misc
        print_dbg("<><><><> Saving '_Mbase.png' <><><><>")
        cv.SaveImage("_Mbase.png", I)
        print_dbg("<><><><> Saving '_M.png' <><><><>")
        scipy.misc.imsave("_M.png", M)
        pdb.set_trace()
    cv.SetImageROI(I, roi_prev)
    i = 0
    xs = []
    _xamt, _yamt = int(round(AX * w_A)), int(round(AY * h_A))
    while i < K:
        minResp, maxResp, minLoc, maxLoc = cv.MinMaxLoc(M)
        if maxResp < T:
            break
        x, y = maxLoc
        # Find the /leftmost/ match: don't find a match in the middle
        # of a column.
        while M[y, x] >= T:
            x -= 1
        xs.append((x + bb[0]))
        _x1 = max(1, x - _xamt)
        _x2 = max(1, x + _xamt)
        _y1 = max(1, y - _yamt)
        _y2 = max(1, y + _yamt)
        M[_y1:_y2, _x1:_x2] = -1.0
        i += 1
    if not xs:
        return None
    elif len(xs) == 1:
        return xs[0]
    return np.median(xs)
Example #13
0
    def set_new_position(self, points_or_corners, offset=True, scale=1):
        '''
        Sets new position for this marker using points (in order)
        @param points_or_corners: list of points or corners
        @param offset: if true, image ROI is checked and points are shifted
        '''
        if len(points_or_corners) > 0 and type(points_or_corners[0]) == tuple:
            self.predicted = -1
            points = points_or_corners
            img = self.m_d.img
            (x, y, _, _) = rect = cv.GetImageROI(img)
            if offset and (x, y) <> (0, 0):
                points = map(lambda z: add((x, y), z), points)
            cv.ResetImageROI(img)
            crit = (cv.CV_TERMCRIT_EPS + cv.CV_TERMCRIT_ITER, 30, 0.1)
            if (scale > 1):
                points = cv.FindCornerSubPix(self.m_d.gray_img, points,
                                             (scale * 2 + 4, scale * 2 + 4),
                                             (-1, -1), crit)
            else:
                points = cv.FindCornerSubPix(self.m_d.gray_img, points, (3, 3),
                                             (-1, -1), crit)
            ncorners = Corner.get_corners(points, self.m_d.time)
            if len(self.corners) <> 0:
                for i, cor in enumerate(ncorners):
                    cor.compute_change(self.corners[i])
            cv.SetImageROI(img, rect)
        else:
            ncorners = points_or_corners
            self.predicted += len(filter(lambda x: x.is_predicted, ncorners))
        for i, c in enumerate(ncorners):
            c.black_inside = self.black_inside
#            if len(self.corners)==4:
#                if dist_points(c.p, self.corners[i].p)<4:
#                    c.p=self.corners[i].p
        self.corners = ncorners

        self.area = abs(cv.ContourArea(self.points))
        self.last_seen = self.m_d.time
        self.model_view = None
Example #14
0
    def process_frame(self, frame):

        # Resize image to 320x240
        #copy = cv.CreateImage(cv.GetSize(frame), 8, 3)
        #cv.Copy(frame, copy)
        #cv.SetImageROI(frame, (0, 0, 320, 240))
        #cv.Resize(copy, frame, cv.CV_INTER_NN)

        found_hedge = False

        cv.Smooth(frame, frame, cv.CV_MEDIAN, 7, 7)

        # Set binary image to have value channel
        hsv = cv.CreateImage(cv.GetSize(frame), 8, 3)
        binary = cv.CreateImage(cv.GetSize(frame), 8, 1)
        cv.CvtColor(frame, hsv, cv.CV_BGR2HSV)
        cv.SetImageCOI(hsv, 1)
        cv.Copy(hsv, binary)
        cv.SetImageCOI(hsv, 0)

        cv.AdaptiveThreshold(
            binary,
            binary,
            255,
            cv.CV_ADAPTIVE_THRESH_MEAN_C,
            cv.CV_THRESH_BINARY_INV,
            self.adaptive_thresh_blocksize,
            self.adaptive_thresh,
        )

        # Morphology
        '''
        kernel = cv.CreateStructuringElementEx(3, 3, 1, 1, cv.CV_SHAPE_ELLIPSE)
        cv.Erode(binary, binary, kernel, 1)
        cv.Dilate(binary, binary, kernel, 1)
        '''
        if self.debug:
            color_filtered = cv.CloneImage(binary)

        # Get Edges
        #cv.Canny(binary, binary, 30, 40)

        # Hough Transform
        line_storage = cv.CreateMemStorage()
        raw_lines = cv.HoughLines2(binary,
                                   line_storage,
                                   cv.CV_HOUGH_STANDARD,
                                   rho=1,
                                   theta=math.pi / 180,
                                   threshold=self.hough_threshold,
                                   param1=0,
                                   param2=0)

        # Get vertical lines
        vertical_lines = []
        for line in raw_lines:
            if line[1] < self.vertical_threshold or \
                    line[1] > math.pi - self.vertical_threshold:

                vertical_lines.append((abs(line[0]), line[1]))

        # Group vertical lines
        vertical_line_groups = [
        ]  # A list of line groups which are each a line list
        for line in vertical_lines:
            group_found = False
            for line_group in vertical_line_groups:

                if line_group_accept_test(line_group, line, self.max_range):
                    line_group.append(line)
                    group_found = True

            if not group_found:
                vertical_line_groups.append([line])

        # Average line groups into lines
        vertical_lines = []
        for line_group in vertical_line_groups:
            rhos = map(lambda line: line[0], line_group)
            angles = map(lambda line: line[1], line_group)
            line = (sum(rhos) / len(rhos), circular_average(angles, math.pi))
            vertical_lines.append(line)

        # Get horizontal lines
        horizontal_lines = []
        for line in raw_lines:
            dist_from_horizontal = (math.pi / 2 + line[1]) % math.pi
            if dist_from_horizontal < self.horizontal_threshold or \
                    dist_from_horizontal > math.pi - self.horizontal_threshold:

                horizontal_lines.append((abs(line[0]), line[1]))

        # Group horizontal lines
        horizontal_line_groups = [
        ]  # A list of line groups which are each a line list
        for line in horizontal_lines:
            group_found = False
            for line_group in horizontal_line_groups:

                if line_group_accept_test(line_group, line, self.max_range):
                    line_group.append(line)
                    group_found = True

            if not group_found:
                horizontal_line_groups.append([line])

        if len(horizontal_line_groups) is 1:
            self.seen_crossbar = True
            rhos = map(lambda line: line[0], horizontal_line_groups[0])
            angles = map(lambda line: line[1], horizontal_line_groups[0])
            line = (sum(rhos) / len(rhos), circular_average(angles, math.pi))
            horizontal_lines = [line]
        else:
            self.seen_crossbar = False
            horizontal_lines = []

        self.left_pole = None
        self.right_pole = None
        if len(vertical_lines) is 2:
            roi = cv.GetImageROI(frame)
            width = roi[2]
            height = roi[3]
            self.left_pole = round(
                min(vertical_lines[0][0], vertical_lines[1][0]), 2) - width / 2
            self.right_pole = round(
                max(vertical_lines[0][0], vertical_lines[1][0]), 2) - width / 2
        # TODO: If one pole is seen, is it left or right pole?

        # Calculate planar distance r (assuming we are moving perpendicular to
        # the hedge)
        if self.left_pole and self.right_pole:
            theta = abs(self.left_pole - self.right_pole)
            self.r = 3 / tan(radians(theta / 2))
        else:
            self.r = None

        if self.r and self.seen_crossbar:
            bar_phi = (-1 * horizontal_lines[0][0] +
                       frame.height / 2) / (frame.height / 2) * 32
            self.crossbar_depth = self.r * atan(radians(bar_phi))
        else:
            self.crossbar_depth = None

        if self.debug:
            cv.CvtColor(color_filtered, frame, cv.CV_GRAY2RGB)
            libvision.misc.draw_lines(frame, vertical_lines)
            libvision.misc.draw_lines(frame, horizontal_lines)

            #cv.ShowImage("Hedge", cv.CloneImage(frame))
            svr.debug("Hedge", cv.CloneImage(frame))

        # populate self.output with infos
        self.output.seen_crossbar = self.seen_crossbar
        self.output.left_pole = self.left_pole
        self.output.right_pole = self.right_pole
        self.output.r = self.r
        self.output.crossbar_depth = self.crossbar_depth

        self.return_output()
        print self
Example #15
0
    def process_frame(self, frame):
        ################
        #setup CV ######
        ################
        print "processing frame"
        (w, h) = cv.GetSize(frame)

        #generate hue selection frames
        ones = np.ones((h, w, 1), dtype='uint8')
        a = ones * (180 - self.target_hue)
        b = ones * (180 - self.target_hue + 20)
        a_array = cv.fromarray(a)
        b_array = cv.fromarray(b)

        #create locations for the test frame and binary frame
        frametest = cv.CreateImage(cv.GetSize(frame), 8, 3)
        binarytest = cv.CreateImage(cv.GetSize(frame), 8, 1)

        #use the red channel for the binary frame (just for debugging purposes)
        cv.Copy(frame, frametest)
        cv.SetImageCOI(frametest, 3)
        cv.Copy(frametest, binarytest)

        #reset the COI for test frame to RGB.
        cv.SetImageCOI(frametest, 0)

        # Resize image to 320x240
        #copy = cv.CreateImage(cv.GetSize(frame), 8, 3)
        #cv.Copy(frame, copy)
        #cv.SetImageROI(frame, (0, 0, 320, 240))
        #cv.Resize(copy, frame, cv.CV_INTER_NN)
        found_gate = False

        #create a new frame for comparison purposes
        unchanged_frame = cv.CreateImage(cv.GetSize(frame), 8, 3)
        cv.Copy(frame, unchanged_frame)

        #apply noise filter #1
        cv.Smooth(frame, frame, cv.CV_MEDIAN, 7, 7)

        # Set binary image to have saturation channel
        hsv = cv.CreateImage(cv.GetSize(frame), 8, 3)
        binary = cv.CreateImage(cv.GetSize(frame), 8, 1)
        cv.CvtColor(frame, hsv, cv.CV_BGR2HSV)
        cv.SetImageCOI(hsv, 1)
        cv.Copy(hsv, binary)

        #spin the color wheel (psuedo-code for later if necessary)
        # truncate spectrum marked as end
        # shift all values up based on truncating value (mask out 0 regions)
        # take truncated bits, and flip them (180->0, 179->1...)
        # dnow that truncated bits are flipped, add them back in to final image

        #Reset hsv COI
        cv.SetImageCOI(hsv, 0)

        #correct for wraparound on red spectrum
        cv.InRange(binary, a_array, b_array, binarytest)  #generate mask
        cv.Add(binary, cv.fromarray(ones * 180), binary,
               mask=binarytest)  #use mask to selectively add values

        #run adaptive threshold for edge detection
        cv.AdaptiveThreshold(
            binary,
            binary,
            255,
            cv.CV_ADAPTIVE_THRESH_MEAN_C,
            cv.CV_THRESH_BINARY_INV,
            self.adaptive_thresh_blocksize,
            self.adaptive_thresh,
        )

        # Morphology
        kernel = cv.CreateStructuringElementEx(5, 5, 3, 3, cv.CV_SHAPE_ELLIPSE)
        cv.Erode(binary, binary, kernel, 1)
        cv.Dilate(binary, binary, kernel, 1)
        if self.debug:
            color_filtered = cv.CloneImage(binary)

        # Get Edges
        cv.Canny(binary, binary, 30, 40)

        # Hough Transform
        line_storage = cv.CreateMemStorage()
        raw_lines = cv.HoughLines2(binary,
                                   line_storage,
                                   cv.CV_HOUGH_STANDARD,
                                   rho=1,
                                   theta=math.pi / 180,
                                   threshold=self.hough_threshold,
                                   param1=0,
                                   param2=0)

        # Get vertical lines
        vertical_lines = []
        i = 0
        for line in raw_lines:
            if line[1] < self.vertical_threshold or \
                line[1] > (math.pi-self.vertical_threshold):

                #absolute value does better grouping currently
                vertical_lines.append((abs(line[0]), line[1]))
            i += 1

        # print message to user for performance purposes
        logging.debug("{} possibilities reduced to {} lines".format(
            i, len(vertical_lines)))

        # Group vertical lines
        vertical_line_groups = [
        ]  #A list of line groups which are each a line list
        i = 0
        for line in vertical_lines:
            group_found = False
            for line_group in vertical_line_groups:
                i += 1
                if line_group_accept_test(line_group, line, self.max_range):
                    line_group.append(line)
                    group_found = True

            if not group_found:
                vertical_line_groups.append([line])

        #quick debugging statement
        logging.debug("{} internal iterations for {} groups".format(
            i, len(vertical_line_groups)))

        # Average line groups into lines
        vertical_lines = []
        for line_group in vertical_line_groups:
            rhos = map(lambda line: line[0], line_group)  #get rho of each line
            angles = map(lambda line: line[1], line_group)
            line = (sum(rhos) / len(rhos), circular_average(angles, math.pi))
            vertical_lines.append(line)

        self.left_pole = None
        self.right_pole = None
        self.returning = 0
        self.found = False

        if len(vertical_lines) is 2:
            roi = cv.GetImageROI(frame)
            width = roi[2]
            height = roi[3]
            self.left_pole = round(
                min(vertical_lines[0][0], vertical_lines[1][0]), 2) - width / 2
            self.right_pole = round(
                max(vertical_lines[0][0], vertical_lines[1][0]), 2) - width / 2

            self.returning = (self.left_pole + self.right_pole) / 2
            logging.info("Returning {}".format(self.returning))

            #If this is first iteration, count this as seeing the gate
            if self.last_seen < 0:
                self.last_center = None
                self.last_seen = 0

            #increment a counter if result is good.
            if self.last_center is None:
                self.last_center = self.returning
                self.seen_count = 1
            elif math.fabs(self.last_center -
                           self.returning) < self.center_trans_thresh:
                self.seen_count += 1
                self.last_seen += 2
            else:
                self.last_seen -= 1

            #if not convinced, forget left/right pole. Else, proclaim success.
            if self.seen_count < self.seen_count_thresh:
                self.left_pole = None
                self.right_pole = None
            else:
                print "FOUND CENTER AND RETURNED IT"
                self.found = True

        else:
            self.returning = 0

            if self.last_seen < 0:
                self.last_center = None
                self.last_seen = 0

            self.last_seen -= 1
            self.left_pole = None
            self.right_POLE = None

        #extra debugging stuff
        if self.debug:
            cv.CvtColor(color_filtered, frame, cv.CV_GRAY2RGB)
            libvision.misc.draw_lines(frame, vertical_lines)

            if self.found:
                cv.Circle(frame, (int(frame.width / 2 + self.returning),
                                  int(frame.height / 2)), 15, (0, 255, 0), 2,
                          8, 0)
                font = cv.InitFont(cv.CV_FONT_HERSHEY_SIMPLEX, 1, 1, 1, 3)
                cv.PutText(frame, "Gate Sent to Mission Control", (100, 400),
                           font, (255, 255, 0))
                #print frame.width

        #cv.ShowImage("Gate", cv.CloneImage(frame))
        svr.debug("Gate", cv.CloneImage(frame))
        svr.debug("Unchanged", cv.CloneImage(unchanged_frame))

        self.return_output()
def shift_roi(I, x, y, w, h):
    roi_prev = cv.GetImageROI(I)
    new_roi = tuple(map(int, (roi_prev[0] + x, roi_prev[1] + y, w, h)))
    cv.SetImageROI(I, new_roi)
    return I
def decode_i2of5(img,
                 n,
                 topbot_pairs,
                 orient=VERTICAL,
                 debug=False,
                 imgP=None,
                 cols=4):
    """ Decodes the interleaved two-of-five barcode. Returns a string.
    Input:
        IplImage img:
        int n: Number of digits in the barcode.
        list TOPBOT_PAIRS: [[IplImage topguard, IplImage botguard], ...]. 
        int COLS: Splits the barcode into COLS columns, separately
            runs the decoding on each column, then chooses the most
            popular decoding result.
    Output:
        (str decoded, tuple bb), where BB is the bounding box of the
        barcode within IMG: (x, y, w, h)
    """
    # For now, assume that the barcode is bottom-to-top.
    TOP_GUARD, BOT_GUARD = topbot_pairs[0]

    TOP_GUARD = smooth_constborder(TOP_GUARD, xwin=3, ywin=3, val=255)
    BOT_GUARD = smooth_constborder(BOT_GUARD, xwin=3, ywin=3, val=255)

    TOP_WHITE_PAD = 24  # Num. pixs from white->top guard barcode
    BOT_WHITE_PAD = 31

    # 1.) Find location of top/bottom guards, to find location of barcode
    bc_height = BC_14_HEIGHT if n == 14 else BC_12_HEIGHT
    bc_loc = find_barcode_loc_tm(img,
                                 bc_height,
                                 TOP_GUARD,
                                 BOT_GUARD,
                                 TOP_WHITE_PAD,
                                 BOT_WHITE_PAD,
                                 imgP=imgP)
    if bc_loc == None:
        if len(topbot_pairs) == 1:
            return None, [0, 0, 1, 1], None
        return decode_i2of5(img,
                            n,
                            topbot_pairs[1:],
                            imgP=imgP,
                            cols=cols,
                            debug=debug)

    # 2.) Crop the barcode.
    #cv.SaveImage("_imgcrop_pre.png", img)
    roi_precrop = cv.GetImageROI(img)
    cv.SetImageROI(img, shiftROI(cv.GetImageROI(img), bc_loc))
    #cv.SaveImage("_imgcrop.png", img)
    decodings = []
    w_bc, h_bc = cv.GetSize(img)
    bc_roi = cv.GetImageROI(img)
    for curcol in xrange(cols):
        width = int(round(w_bc / cols))
        x1 = width * curcol
        cv.SetImageROI(img, shiftROI(bc_roi, (x1, 0, width, h_bc)))
        decodings.append(
            decode_barcode(img, n, bc_loc[:], xoff=x1, imgP=imgP, debug=debug))

    dstr_out, bbloc_out, bbstripes_out = get_most_popular(decodings, w_bc)
    cv.SetImageROI(img, roi_precrop)

    if dstr_out == None:
        if len(topbot_pairs) == 1:
            # We tried our best, give up.
            return dstr_out, bbloc_out, bbstripes_out
        else:
            return decode_i2of5(img,
                                n,
                                topbot_pairs[1:],
                                imgP=imgP,
                                cols=cols,
                                debug=debug)
    return dstr_out, bbloc_out, bbstripes_out
def decoder_v2_helper(I,
                      Icol,
                      bbs_rough,
                      w_markfull,
                      h_markfull,
                      isflip,
                      H_GAP,
                      theta,
                      i1_blk,
                      i2_blk,
                      j1_blk,
                      j2_blk,
                      imgpath=None,
                      find_col=True,
                      W_MARK=WIDTH_MARK,
                      H_MARK=HEIGHT_MARK,
                      idx2tol=None):
    result = None
    roi_prev = cv.GetImageROI(I)
    w, h = cv.GetSize(I)

    if find_col:
        w, h = cv.GetSize(I)
        bb_left = (0.0, 0.86 * h, 0.06 * w, h - 1)
        bb_right = ((w - 1) - (0.06 * w), 0.86 * h, w - 1, h - 1)
        if DEBUG_SAVEIMGS:
            print_dbg("<><><><> Saving '_Inocolflush.png' <><><><>")
            cv.SaveImage("_Inocolflush.png", I)
        x1_left = find_col_x1(I, Icol, bb_left)
        x1_right = find_col_x1(I, Icol, bb_right)
        print_dbg("== x1_left={0} x1_right={1}".format(x1_left, x1_right))
        x1_left = x1_left if x1_left != None else 0
        x1_right = (min(h - 1, x1_right +
                        w_markfull) if x1_right != None else w - 1)
    else:
        x1_left, x1_right = 0, w - 1
    bb_thecols = (x1_left, 0, x1_right, h - 1)
    shift_roi(I, bb_thecols[0], bb_thecols[1], bb_thecols[2] - bb_thecols[0],
              bb_thecols[3] - bb_thecols[1])
    roi_flushcol = cv.GetImageROI(I)
    if DEBUG_SAVEIMGS:
        print_dbg("<><><><> Saving '_Iflushcols.png' <><><><>")
        cv.SaveImage("_Iflushcols.png", I)
        pdb.set_trace()
    for bb_rough in bbs_rough:
        cv.SetImageROI(I, roi_flushcol)
        shift_roi(I, bb_rough[0], bb_rough[1], bb_rough[2] - bb_rough[0],
                  bb_rough[3] - bb_rough[1])
        w_foo, h_foo = cv.GetSize(I)
        Icor, H = rotate_img(I, -theta)

        Hfoo = np.eye(3)
        Hfoo[0:2, 0:3] = np.array(H)
        H_inv = np.linalg.inv(Hfoo)
        H_inv = H_inv[0:2]

        if DEBUG_SAVEIMGS:
            print_dbg("<><><><> Saving '_Icor.png' <><><><>")
            cv.SaveImage("_Icor.png", Icor)
        i1_blk_cor, i2_blk_cor, j1_blk_cor, j2_blk_cor = compute_border(
            iplimage2np(Icor))
        shift_roi(Icor, j1_blk_cor, i1_blk_cor,
                  cv.GetSize(Icor)[0] - (j1_blk_cor + j2_blk_cor),
                  cv.GetSize(Icor)[1] - (i1_blk_cor + i2_blk_cor))

        if DEBUG_SAVEIMGS:
            print_dbg("<><><><> Saving '_Icor_noblkborder.png' <><><><>")
            cv.SaveImage("_Icor_noblkborder.png", Icor)

        def to_orig_coords(bb, H_inv):
            """ Returns BB (in corrected coord. system) to the original
            coordinate system.
            """
            x1, y1 = transform_pt((bb[0], bb[1]), H_inv, (w_foo, h_foo))
            x1 += bb_rough[0] + bb_thecols[0]
            y1 += bb_rough[1]
            x2, y2 = transform_pt((bb[2], bb[3]), H_inv, (w_foo, h_foo))
            x2 += bb_rough[0] + bb_thecols[0]
            y2 += bb_rough[1]
            return tuple(map(lambda x: int(round(x)), (x1, y1, x2, y2)))

        w_cor, h_cor = cv.GetSize(Icor)
        candidates = []
        y1_step = int(h_markfull / 4.0)

        def tighten_bbs(bbs, decoding, I):
            """ Given initial boundingboxes around each mark, compute
            new bbs such that each 'on' mark is at the upper-left corner.
            """
            def find_black(I, x, BLACK=130, y1_start=0):
                """ Find y1 of first black pixel, starting from (X, 0). """
                w, h = cv.GetSize(I)
                for y1 in xrange(y1_start, h):
                    if I[y1, x] <= BLACK:
                        return y1
                return None

            w_img, h_img = cv.GetSize(I)
            bbs_out = []
            y1s_ons = []
            if DEBUG_SAVEIMGS:
                print_dbg("<><><><> Saving '_Itightenbbs.png' <><><><>")
                cv.SaveImage("_Itightenbbs.png", I)
            # First, estimate the y1's for the left/right col marks,
            # since they're the 'easiest' to find
            y1s_leftright = []
            for (x1, y1, x2, y2) in (bbs[0], bbs[-1]):
                w_rect, h_rect = (x2 - x1), (y2 - y1)
                x1s = (x1 + int(w_rect * 0.15), x1 + int(w_rect / 4.0),
                       x1 + int(w_rect / 2.0), x1 + int(
                           (3 * w_rect) / 4.0), (x2 - 1) - int(w_rect * 0.1))
                x1s = [x for x in x1s if x < w_img]
                y1s = [find_black(I, x1_cur, y1_start=0) for x1_cur in x1s]
                y1s = [_y1 for _y1 in y1s if _y1 != None]
                if not y1s:
                    y1_out = 0  # Default to sensible value
                else:
                    y1_out = int(round(np.median(y1s)))
                y1s_leftright.append(y1_out)

            for i, (x1, y1, x2, y2) in enumerate(bbs):
                val = decoding[i]
                if val == '0':
                    bbs_out.append((x1, y1, x2, y2))
                    continue
                w_rect, h_rect = (x2 - x1), (y2 - y1)
                x1s = (x1 + int(w_rect * 0.15), x1 + int(w_rect / 4.0),
                       x1 + int(w_rect / 2.0), x1 + int(
                           (3 * w_rect) / 4.0), (x2 - 1) - int(w_rect * 0.1))
                x1s = [x for x in x1s if x < w_img]
                if i == 0 or i == len(bbs) - 1:
                    _y1 = 0
                else:
                    _y1 = max(int(round(y1 - (h_markfull / 4.0))), 0)

                y1s = [find_black(I, x1_cur, y1_start=_y1) for x1_cur in x1s]
                y1s = [_y1 for _y1 in y1s
                       if _y1 != None]  # Filter out the bad results

                #y1_out = int(round((np.mean(y1s)+np.median(y1s))/2.0))
                if not y1s:
                    y1_out = 0  # Default to sensible value
                else:
                    y1_out = int(round(np.median(y1s)))
                y2_out = y1_out + (y2 - y1) - 1
                y1s_ons.append(y1_out)
                bbs_out.append((x1, y1_out - 1, x2, y2_out - 1))
            # Finally, clamp all y1s of '0' marks to some fixed y1
            y1_clamp = int(round(np.mean(y1s_ons)))
            bbs_out_final = []
            for i, (x1, y1, x2, y2) in enumerate(bbs_out):
                if decoding[i] == '0':
                    bbs_out_final.append(
                        (x1, y1_clamp, x2, y1_clamp + (y2 - y1) - 1))
                else:
                    bbs_out_final.append((x1, y1, x2, y2))
            return bbs_out_final

        for step in xrange(int((h_cor - 1) / y1_step)):
            if step == 0:
                shift_roi(Icor, 0, 0, w_cor, h_markfull)
            else:
                # Don't shift down on first iteration!
                shift_roi(Icor, 0, y1_step, w_cor, h_markfull)
            if DEBUG_SAVEIMGS:
                print_dbg("<><><><> Saving '_Icor_strip.ong' <><><><>")
                cv.SaveImage("_Icor_strip.png", Icor)
                pdb.set_trace()

            # list SYMS := [(str VAL, int X1), ...]
            syms, params_ = scan_bars.parse_patch(Icor,
                                                  (w_markfull, h_markfull),
                                                  gap=H_GAP,
                                                  LEN=34,
                                                  orient=scan_bars.HORIZONTAL,
                                                  MARKTOL=0.7,
                                                  BEGIN_TOL=0.3,
                                                  END_TOL=0.3,
                                                  GAMMA=0.7,
                                                  idx2tol=idx2tol)
            decoding = ''.join([t[0] for t in syms])
            pix_on, pix_off = params_["pix_on"], params_["pix_off"]

            def is_pixon_pixoff_ok():
                if PIX_ON_OFF_RATIO != None:
                    return (pix_on / pix_off) < PIX_ON_OFF_RATIO
                else:
                    return True

            if not sanitycheck_decoding_v2(decoding) or (
                    not is_pixon_pixoff_ok()):
                print_dbg("(SanityCheck) FAIL -- '{0}' ({1})".format(
                    decoding, len(decoding)))
                continue

            if EXP_PARAMS:
                global GLOB_PARAMS_
                if GLOB_PARAMS_ == None:
                    GLOB_PARAMS_ = {"PIX_ON": [], "PIX_OFF": []}
                GLOB_PARAMS_["PIX_ON"].append(params_['pix_on'])
                GLOB_PARAMS_["PIX_OFF"].append(params_['pix_off'])

            markbbs_rough = [(t[1], 0, t[1] + W_MARK, H_MARK - 1)
                             for t in syms]
            # Find a tighter y1 for the black marks
            bbs = tighten_bbs(markbbs_rough, decoding, Icor)
            # Correct for current-offset in sweep
            #bbs_out = [(t[1], y1_step*step, t[1] + w_markfull, y1_step*step + h_markfull) for t in syms]
            bbs_out = [(t[0], t[1] + (y1_step * step), t[2],
                        t[3] + (y1_step * step)) for t in bbs]
            # Undo rotation correction
            bbs_out = [to_orig_coords(bb, H_inv) for bb in bbs_out]
            # Add the compute_border offsets (part1)
            bbs_out = [(x1 + j1_blk_cor, y1 + i1_blk_cor, x2 + j1_blk_cor,
                        y2 + i1_blk_cor) for (x1, y1, x2, y2) in bbs_out]
            # Add the compute_border offsets
            #bbs_out = [(x1+j1_blk, y1+i1_blk, x2+j1_blk, y2+i2_blk) for (x1,y1,x2,y2) in bbs_out]
            bbs_out = [(x1 + j1_blk, y1 + i1_blk, (x1 + W_MARK - 1) + j1_blk,
                        (y1 + H_MARK - 1) + i1_blk)
                       for (x1, y1, x2, y2) in bbs_out]
            if DEBUG_SAVEIMGS:
                print_dbg("==== decoding ({0}): {1}".format(
                    len(decoding), decoding))
                Icolor = draw_bbs(imgpath, decoding, bbs_out, isflip)
                cv.SaveImage("_dbg_showit.png", Icolor)
                print "<><><><> Saving '_dbg_showit.png' <><><><>"
                dbg_bbs_out = [(t[1], y1_step * step, t[1] + w_markfull,
                                y1_step * step + h_markfull) for t in syms]
                # Undo rotation correction
                dbg_bbs_out = [to_orig_coords(bb, H_inv) for bb in dbg_bbs_out]
                # Add the compute_border offsets (part1)
                dbg_bbs_out = [(x1 + j1_blk_cor, y1 + i1_blk_cor,
                                x2 + j1_blk_cor, y2 + i2_blk_cor)
                               for (x1, y1, x2, y2) in dbg_bbs_out]
                # Add the compute_border offsets
                dbg_bbs_out = [(x1 + j1_blk, y1 + i1_blk, x2 + j1_blk,
                                y2 + i2_blk)
                               for (x1, y1, x2, y2) in dbg_bbs_out]
                Icolor_notighten = draw_bbs(imgpath, decoding, dbg_bbs_out,
                                            isflip)
                cv.SaveImage("_dbg_showit_notighten.png", Icolor_notighten)
                print "<><><><> Saving '_dbg_showit_notighten.png' <><><><>"
                pdb.set_trace()

            if sanitycheck_decoding_v2(decoding):
                candidates.append((decoding, isflip, bbs_out))
        if candidates:
            result = most_popular(candidates, W_MARK=W_MARK, H_MARK=H_MARK)
        if result != None:
            break
        print_dbg("==== Trying another bb_rough")
    cv.SetImageROI(I, roi_prev)
    return result
Example #19
0
    def process_frame(self, frame):
        frametest = cv.CreateImage(cv.GetSize(frame), 8, 3)
        binarytest = cv.CreateImage(cv.GetSize(frame), 8, 1)

        cv.Copy(frame, frametest)
        cv.SetImageCOI(frametest, 3)
        cv.Copy(frametest, binarytest)
        cv.SetImageCOI(frametest, 0)
        svr.debug("R?", binarytest)

        # Resize image to 320x240
        #copy = cv.CreateImage(cv.GetSize(frame), 8, 3)
        #cv.Copy(frame, copy)
        #cv.SetImageROI(frame, (0, 0, 320, 240))
        #cv.Resize(copy, frame, cv.CV_INTER_NN)

        found_gate = False

        unchanged_frame = cv.CreateImage(cv.GetSize(frame), 8, 3)
        cv.Copy(frame, unchanged_frame)

        cv.Smooth(frame, frame, cv.CV_MEDIAN, 7, 7)

        # Set binary image to have saturation channel
        hsv = cv.CreateImage(cv.GetSize(frame), 8, 3)
        binary = cv.CreateImage(cv.GetSize(frame), 8, 1)
        cv.CvtColor(frame, hsv, cv.CV_BGR2HSV)
        cv.SetImageCOI(hsv, 1)
        cv.Copy(hsv, binary)
        cv.SetImageCOI(hsv, 0)

        cv.AdaptiveThreshold(
            binary,
            binary,
            255,
            cv.CV_ADAPTIVE_THRESH_MEAN_C,
            cv.CV_THRESH_BINARY_INV,
            self.adaptive_thresh_blocksize,
            self.adaptive_thresh,
        )

        # Morphology
        kernel = cv.CreateStructuringElementEx(5, 5, 3, 3, cv.CV_SHAPE_ELLIPSE)
        cv.Erode(binary, binary, kernel, 1)
        cv.Dilate(binary, binary, kernel, 1)
        if self.debug:
            color_filtered = cv.CloneImage(binary)

        # Get Edges
        cv.Canny(binary, binary, 30, 40)

        # Hough Transform
        line_storage = cv.CreateMemStorage()
        raw_lines = cv.HoughLines2(binary,
                                   line_storage,
                                   cv.CV_HOUGH_STANDARD,
                                   rho=1,
                                   theta=math.pi / 180,
                                   threshold=self.hough_threshold,
                                   param1=0,
                                   param2=0)

        # Get vertical lines
        vertical_lines = []
        for line in raw_lines:
            if line[1] < self.vertical_threshold or \
               line[1] > math.pi-self.vertical_threshold:

                #absolute value does better grouping currently
                vertical_lines.append((abs(line[0]), line[1]))

        # Group vertical lines
        vertical_line_groups = [
        ]  # A list of line groups which are each a line list
        for line in vertical_lines:
            group_found = False
            for line_group in vertical_line_groups:

                if line_group_accept_test(line_group, line, self.max_range):
                    line_group.append(line)
                    group_found = True

            if not group_found:
                vertical_line_groups.append([line])

        # Average line groups into lines
        vertical_lines = []
        for line_group in vertical_line_groups:
            rhos = map(lambda line: line[0], line_group)
            angles = map(lambda line: line[1], line_group)
            line = (sum(rhos) / len(rhos), circular_average(angles, math.pi))
            vertical_lines.append(line)

        # Get horizontal lines
        horizontal_lines = []
        for line in raw_lines:
            dist_from_horizontal = (math.pi / 2 + line[1]) % math.pi
            if dist_from_horizontal < self.horizontal_threshold or \
               dist_from_horizontal > math.pi-self.horizontal_threshold:

                horizontal_lines.append((abs(line[0]), line[1]))

        # Group horizontal lines
        horizontal_line_groups = [
        ]  # A list of line groups which are each a line list
        for line in horizontal_lines:
            group_found = False
            for line_group in horizontal_line_groups:

                if line_group_accept_test(line_group, line, self.max_range):
                    line_group.append(line)
                    group_found = True

            if not group_found:
                horizontal_line_groups.append([line])

        if len(horizontal_line_groups) is 1:
            self.seen_crossbar = True
            if self.debug:
                rhos = map(lambda line: line[0], horizontal_line_groups[0])
                angles = map(lambda line: line[1], horizontal_line_groups[0])
                line = (sum(rhos) / len(rhos),
                        circular_average(angles, math.pi))
                horizontal_lines = [line]
        else:
            self.seen_crossbar = False
            horizontal_lines = []

        self.left_pole = None
        self.right_pole = None
        print vertical_lines
        self.returning = 0
        self.found = False
        if len(vertical_lines) is 2:
            roi = cv.GetImageROI(frame)
            width = roi[2]
            height = roi[3]
            self.left_pole = round(
                min(vertical_lines[0][0], vertical_lines[1][0]), 2) - width / 2
            self.right_pole = round(
                max(vertical_lines[0][0], vertical_lines[1][0]), 2) - width / 2

            self.returning = (self.left_pole + self.right_pole) / 2
            print "Returning ", self.returning

            if self.last_seen < 0:
                self.last_center = None
                self.last_seen = 0
            if self.last_center is None:
                self.last_center = self.returning
                self.seen_count = 1
            elif math.fabs(self.last_center -
                           self.returning) < self.center_trans_thresh:
                self.seen_count += 1
                self.last_seen += 2
            else:
                self.last_seen -= 1

            if self.seen_count < self.seen_count_thresh:
                self.left_pole = None
                self.right_pole = None
            else:
                print "FOUND CENTER AND RETURNED IT"
                self.found = True
        else:
            self.returning = 0
            if self.last_seen < 0:
                self.last_center = None
                self.last_seen = 0
            self.last_seen -= 1
            self.left_pole = None
            self.right_pole = None

        #TODO: If one pole is seen, is it left or right pole?

        if self.debug:
            cv.CvtColor(color_filtered, frame, cv.CV_GRAY2RGB)
            libvision.misc.draw_lines(frame, vertical_lines)
            libvision.misc.draw_lines(frame, horizontal_lines)

            if self.found:
                cv.Circle(frame, (int(frame.width / 2 + self.returning),
                                  int(frame.height / 2)), 15, (0, 255, 0), 2,
                          8, 0)
                font = cv.InitFont(cv.CV_FONT_HERSHEY_SIMPLEX, 1, 1, 1, 3)
                cv.PutText(frame, "Gate Sent to Mission Control", (100, 400),
                           font, (255, 255, 0))
                print frame.width

            #cv.ShowImage("Gate", cv.CloneImage(frame))
            svr.debug("Gate", cv.CloneImage(frame))
            svr.debug("Unchanged", cv.CloneImage(unchanged_frame))

        #populate self.output with infos
        self.output.seen_crossbar = self.seen_crossbar
        self.output.left_pole = self.left_pole
        self.output.right_pole = self.right_pole

        self.return_output()
        print self
Example #20
0
    def process_frame(self, frame):
        (w, h) = cv.GetSize(frame)

        #generate hue selection frames

        #create locations for the a pair of test frames
        frametest = cv.CreateImage(cv.GetSize(frame), 8, 3)
        binarytest = cv.CreateImage(cv.GetSize(frame), 8, 1)

        #use the red channel for the binary frame (just for debugging purposes)
        cv.Copy(frame, frametest)
        cv.SetImageCOI(frametest, 3)
        cv.Copy(frametest, binarytest)
        cv.SetImageCOI(frametest, 0)  #reset COI
        #svr.debug("R?",binarytest)

        # Resize image to 320x240
        #copy = cv.CreateImage(cv.GetSize(frame), 8, 3)
        #cv.Copy(frame, copy)
        #cv.SetImageROI(frame, (0, 0, 320, 240))
        #cv.Resize(copy, frame, cv.CV_INTER_NN)

        found_gate = False

        #create a new frame just for comparison purposes
        unchanged_frame = cv.CreateImage(cv.GetSize(frame), 8, 3)
        cv.Copy(frame, unchanged_frame)

        #apply a course noise filter
        cv.Smooth(frame, frame, cv.CV_MEDIAN, 7, 7)

        # Set binary image to have saturation channel
        hsv = cv.CreateImage(cv.GetSize(frame), 8, 3)
        binary = cv.CreateImage(cv.GetSize(frame), 8, 1)
        cv.CvtColor(frame, hsv, cv.CV_BGR2HSV)
        cv.SetImageCOI(hsv, 1)
        cv.Copy(hsv, binary)
        cv.SetImageCOI(hsv, 0)  #reset COI

        #shift hue of image such that orange->red are at top of spectrum
        '''
        binary = libvision.misc.cv_to_cv2(binary)
        binary = libvision.misc.shift_hueCV2(binary, self.target_shift)
        binary = libvision.misc.cv2_to_cv(binary)
	'''

        #correct for wraparound on red spectrum
        #cv.InRange(binary,a_array,b_array,binarytest) #generate mask
        #cv.Add(binary,cv.fromarray(ones*180),binary,mask=binarytest) #use mask to selectively add values
        svr.debug("R2?", binary)
        svr.debug("R2?", binary)

        #run adaptive threshold for edge detection and more noise filtering
        cv.AdaptiveThreshold(
            binary,
            binary,
            255,
            cv.CV_ADAPTIVE_THRESH_MEAN_C,
            cv.CV_THRESH_BINARY_INV,
            self.adaptive_thresh_blocksize,
            self.adaptive_thresh,
        )

        # Morphology
        kernel = cv.CreateStructuringElementEx(5, 5, 3, 3, cv.CV_SHAPE_ELLIPSE)
        cv.Erode(binary, binary, kernel, 1)
        cv.Dilate(binary, binary, kernel, 1)
        if self.debug:
            color_filtered = cv.CloneImage(binary)

        # Get Edges
        cv.Canny(binary, binary, 30, 40)

        # Hough Transform
        line_storage = cv.CreateMemStorage()
        raw_lines = cv.HoughLines2(binary,
                                   line_storage,
                                   cv.CV_HOUGH_STANDARD,
                                   rho=1,
                                   theta=math.pi / 180,
                                   threshold=self.hough_threshold,
                                   param1=0,
                                   param2=0)

        # Get vertical lines
        vertical_lines = []
        for line in raw_lines:
            if line[1] < self.vertical_threshold or \
               line[1] > math.pi-self.vertical_threshold:

                #absolute value does better grouping currently
                vertical_lines.append((abs(line[0]), line[1]))

        #print message to user for performance purposes
        logging.debug("{} possibilities reduced to {} lines".format(
            len(raw_lines), len(vertical_lines)))

        # Group vertical lines
        vertical_line_groups = [
        ]  # A list of line groups which are each a line list
        i = 0
        for line in vertical_lines:
            group_found = False
            for line_group in vertical_line_groups:
                i += 1
                if line_group_accept_test(line_group, line, self.max_range):
                    line_group.append(line)
                    group_found = True

            if not group_found:
                vertical_line_groups.append([line])

        #quick debugging statement
        logging.debug("{} internal iterations for {} groups".format(
            i, len(vertical_line_groups)))

        # Average line groups into lines
        vertical_lines = []
        for line_group in vertical_line_groups:
            rhos = map(lambda line: line[0], line_group)
            angles = map(lambda line: line[1], line_group)
            line = (sum(rhos) / len(rhos), circular_average(angles, math.pi))
            vertical_lines.append(line)

        ####################################################
        #vvvv Horizontal line code isn't used for anything

        # Get horizontal lines
        horizontal_lines = []
        for line in raw_lines:
            dist_from_horizontal = (math.pi / 2 + line[1]) % math.pi
            if dist_from_horizontal < self.horizontal_threshold or \
               dist_from_horizontal > math.pi-self.horizontal_threshold:

                horizontal_lines.append((abs(line[0]), line[1]))

        # Group horizontal lines
        horizontal_line_groups = [
        ]  # A list of line groups which are each a line list
        for line in horizontal_lines:
            group_found = False
            for line_group in horizontal_line_groups:

                if line_group_accept_test(line_group, line, self.max_range):
                    line_group.append(line)
                    group_found = True

            if not group_found:
                horizontal_line_groups.append([line])

        if len(horizontal_line_groups) is 1:
            self.seen_crossbar = True
            if self.debug:
                rhos = map(lambda line: line[0], horizontal_line_groups[0])
                angles = map(lambda line: line[1], horizontal_line_groups[0])
                line = (sum(rhos) / len(rhos),
                        circular_average(angles, math.pi))
                horizontal_lines = [line]
        else:
            self.seen_crossbar = False
            horizontal_lines = []

        #^^^ Horizontal line code isn't used for anything
        ###################################################

        self.left_pole = None
        self.right_pole = None
        #print vertical_lines
        self.returning = 0
        self.found = False

        if len(vertical_lines) is 2:
            roi = cv.GetImageROI(frame)
            width = roi[2]
            height = roi[3]
            self.left_pole = round(
                min(vertical_lines[0][0], vertical_lines[1][0]), 2) - width / 2
            self.right_pole = round(
                max(vertical_lines[0][0], vertical_lines[1][0]), 2) - width / 2

            self.returning = (self.left_pole + self.right_pole) / 2
            logging.info("Returning {} as gate center delta.".format(
                self.returning))

            #initialize first iteration with 2 known poles
            if self.last_seen < 0:
                self.last_center = None
                self.last_seen = 0

            #increment a counter if result is good.
            if self.last_center is None:
                self.last_center = self.returning
                self.seen_count = 1
            elif math.fabs(self.last_center -
                           self.returning) < self.center_trans_thresh:
                self.seen_count += 1
                self.last_seen += 2
            else:
                self.last_seen -= 1

            #if not conviced, forget left/right pole. Else proclaim success.
            if self.seen_count < self.seen_count_thresh:
                self.left_pole = None
                self.right_pole = None
            else:
                print "FOUND CENTER AND RETURNED IT"
                self.found = True
        else:
            self.returning = 0
            if self.last_seen < 0:
                self.last_center = None
                self.last_seen = 0
            self.last_seen -= 1
            self.left_pole = None
            self.right_pole = None

        #TODO: If one pole is seen, is it left or right pole?

        if self.debug:
            cv.CvtColor(color_filtered, frame, cv.CV_GRAY2RGB)
            libvision.misc.draw_lines(frame, vertical_lines)
            libvision.misc.draw_lines(frame, horizontal_lines)

            if self.found:
                cv.Circle(frame, (int(frame.width / 2 + self.returning),
                                  int(frame.height / 2)), 15, (0, 255, 0), 2,
                          8, 0)
                font = cv.InitFont(cv.CV_FONT_HERSHEY_SIMPLEX, 1, 1, 1, 3)
                cv.PutText(frame, "Gate Sent to Mission Control", (100, 400),
                           font, (255, 255, 0))
                #print frame.width

            #cv.ShowImage("Gate", cv.CloneImage(frame))
            svr.debug("Gate", cv.CloneImage(frame))
            svr.debug("Unchanged", cv.CloneImage(unchanged_frame))

        #populate self.output with infos
        self.output.seen_crossbar = self.seen_crossbar
        self.output.left_pole = self.left_pole
        self.output.right_pole = self.right_pole

        self.return_output()
def find_barcode_loc_tm(I,
                        bc_height,
                        TOP_GUARD,
                        BOT_GUARD,
                        TOP_WHITE_PAD,
                        BOT_WHITE_PAD,
                        imgP=None):
    """
    Input:
        IplImage I: Region where a barcode presumably exists.
        int BC_HEIGHT: Estimated height of the barcode.
    Output:
        list BB. [x1, y1, w, h].
        oc_tough_cases/unknown/329_331_25_232_1.png

    """
    w, h = cv.GetSize(I)
    _ROI = cv.GetImageROI(I)
    cv.SetImageROI(I, (_ROI[0], _ROI[1], w, h / 2))
    top_mats = get_tempmatches(TOP_GUARD,
                               I,
                               T=0.86,
                               do_smooth=True,
                               xwin=3,
                               ywin=3,
                               atleastone=True)
    cv.SetImageROI(I, _ROI)
    _ROI = cv.GetImageROI(I)
    cv.SetImageROI(I, (_ROI[0], _ROI[1] + h / 2, w, h / 2))
    bot_mats = get_tempmatches(BOT_GUARD,
                               I,
                               T=0.86,
                               do_smooth=True,
                               xwin=3,
                               ywin=3,
                               atleastone=True)
    cv.SetImageROI(I, _ROI)
    # 1.a.) Get top-most/bottom-most match.
    top_sorted = sorted(top_mats, key=lambda t: t[1])  # (46, 58)
    bot_sorted = sorted(bot_mats, key=lambda t: -t[1])  # (46, 74) => (46, 401)
    if not top_sorted and not bot_sorted:
        if debug:
            print "...couldn't find either TOP/BOT guard..."
        return None
    if top_sorted and bot_sorted:
        besttop, bestbot = top_sorted[0], bot_sorted[0]
        # Check that BESTTOP is actually on top of BESTBOT
        if besttop[1] > bestbot[1]:
            return None
    if top_sorted and not bot_sorted:
        (xtop, ytop, sctop) = top_sorted[0]
        (xbot, ybot, scbot) = xtop, ytop + bc_height, 1.0
    elif bot_sorted and not top_sorted:
        (xbot, ybot, scbot) = bot_sorted[0]
        ybot += h / 2  # Account for cropping done above
        (xtop, ytop, sctop) = xbot, ybot - bc_height, 1.0
    else:
        (xtop, ytop, sctop) = top_sorted[0]
        (xbot, ybot, scbot) = bot_sorted[0]
        ybot += h / 2  # Account for cropping done above
    # 1.b.) Correct for the white-padding from topguard/botguard.
    ytop += TOP_WHITE_PAD
    ybot += (BOT_GUARD.height - BOT_WHITE_PAD)
    # 2.) Try to recover from case where top/bot mat is too high/low.
    if abs((ybot - ytop) - bc_height) >= (0.1 * bc_height):
        # Get the more-confident guard match, and work relative to that one
        if sctop > scbot:
            ybot = ytop + bc_height
        else:
            ytop = ybot - bc_height
    bb = [min(xtop, xbot), ytop, TOP_GUARD.width, int(abs(ybot - ytop))]
    return bb
Example #22
0
    def process_frame(self, frame):
        self.numpy_frame = libvision.cv_to_cv2(frame)
        self.debug_frame = self.numpy_frame.copy()
        self.test_frame = self.numpy_frame.copy()

        self.numpy_frame = cv2.medianBlur(self.numpy_frame, 7)
        self.numpy_frame = cv2.cvtColor(self.numpy_frame, cv2.COLOR_BGR2HSV)

        (rf1, rf2, rf3) = cv2.split(self.numpy_frame)

        Rbinary = rf3
        Gbinary = rf1

        # Adaptive Threshold
        Rbinary = cv2.adaptiveThreshold(Rbinary, 255,
                                        cv2.ADAPTIVE_THRESH_MEAN_C,
                                        cv2.THRESH_BINARY_INV,
                                        self.adaptive_thresh_blocksize,
                                        self.adaptive_thresh)

        Gbinary = cv2.adaptiveThreshold(Gbinary, 255,
                                        cv2.ADAPTIVE_THRESH_MEAN_C,
                                        cv2.THRESH_BINARY_INV,
                                        self.Gadaptive_thresh_blocksize,
                                        self.Gadaptive_thresh)

        # Morphology
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))

        Rbinary = cv2.erode(Rbinary, kernel)
        Rbinary = cv2.dilate(Rbinary, kernel)
        Gbinary = cv2.erode(Gbinary, kernel)
        Gbinary = cv2.dilate(Gbinary, kernel)

        Rframe = cv2.cvtColor(Rbinary, cv2.COLOR_GRAY2RGB)
        Gframe = cv2.cvtColor(Gbinary, cv2.COLOR_GRAY2RGB)

        # Hough Transform
        raw_linesG = cv2.HoughLines(Gbinary,
                                    rho=1,
                                    theta=math.pi / 180,
                                    threshold=self.hough_thresholdG)

        # Get vertical lines
        vertical_linesG = []

        if raw_linesG is None:
            raw_linesG = []

        if len(raw_linesG) > 0:
            for line in raw_linesG[0]:
                rho = line[0]
                theta = line[1]
                if theta < self.vertical_thresholdG or theta > (
                        math.pi - self.vertical_thresholdG):
                    vertical_linesG.append((rho, theta))

        # Group vertical lines
        vertical_line_groupsG = [
        ]  # A list of line groups which are each a line list
        for line in vertical_linesG:
            #print "Green Line Grouping Possibility:", line[0], ", ", line[1]
            group_found = False
            for line_group in vertical_line_groupsG:

                if line_group_accept_test(line_group, line, self.max_range):
                    line_group.append(line)
                    group_found = True

            if not group_found:
                vertical_line_groupsG.append([line])

        # Average line groups into lines
        vertical_linesG = []
        for line_group in vertical_line_groupsG:
            rhos = map(lambda line: line[0], line_group)
            angles = map(lambda line: line[1], line_group)
            line = (sum(rhos) / len(rhos), circular_average(angles, math.pi))
            vertical_linesG.append(line)

        # Get horizontal lines
        horizontal_lines = []
        if len(raw_linesG) > 0:
            for line in raw_linesG[0]:
                rho = line[0]
                theta = line[1]
                dist_from_horizontal = (math.pi / 2 + line[1]) % math.pi
                if dist_from_horizontal < self.horizontal_threshold or dist_from_horizontal > math.pi - self.horizontal_threshold:
                    horizontal_lines.append((abs(line[0]), line[1]))

        # Group horizontal lines
        horizontal_line_groups = [
        ]  # A list of line groups which are each a line list
        for line in horizontal_lines:
            group_found = False
            for line_group in horizontal_line_groups:

                if line_group_accept_test(line_group, line, self.max_range):
                    line_group.append(line)
                    group_found = True

            if not group_found:
                horizontal_line_groups.append([line])

        if len(horizontal_line_groups) is 1:
            self.seen_crossbar = True
            rhos = map(lambda line: line[0], horizontal_line_groups[0])
            angles = map(lambda line: line[1], horizontal_line_groups[0])
            line = (sum(rhos) / len(rhos), circular_average(angles, math.pi))
            horizontal_lines = [line]
        else:
            self.seen_crossbar = False
            horizontal_lines = []

        self.left_pole = None
        self.right_pole = None

        Rframe = libvision.cv2_to_cv(Rframe)
        Gframe = libvision.cv2_to_cv(self.debug_frame)
        Rbinary = libvision.cv2_to_cv(Rbinary)
        self.debug_frame = libvision.cv2_to_cv(self.debug_frame)
        self.test_frame = libvision.cv2_to_cv(self.test_frame)
        Gbinary = libvision.cv2_to_cv(Gbinary)

        if len(vertical_linesG) is 2:
            roi = cv.GetImageROI(frame)
            width = roi[2]
            height = roi[3]
            self.left_pole = round(
                min(vertical_linesG[0][0], vertical_linesG[1][0]),
                2) - width / 2
            self.right_pole = round(
                max(vertical_linesG[0][0], vertical_linesG[1][0]),
                2) - width / 2

        # TODO: If one pole is seen, is it left or right pole?

        # Calculate planar distance r (assuming we are moving perpendicular to
        # the hedge)
        if self.left_pole and self.right_pole:
            theta = abs(self.left_pole - self.right_pole)
            self.r = 3 / math.tan(math.radians(theta / 2))
        else:
            self.r = None

        if self.r and self.seen_crossbar:
            bar_phi = (-1 * horizontal_lines[0][0] +
                       Gframe.height / 2) / (Gframe.height / 2) * 32
            self.crossbar_depth = self.r * math.atan(math.radians(bar_phi))
        else:
            self.crossbar_depth = None

        # Line Finding on Red pvc
        # Hough Transform
        line_storage = cv.CreateMemStorage()
        raw_linesR = cv.HoughLines2(Rbinary,
                                    line_storage,
                                    cv.CV_HOUGH_STANDARD,
                                    rho=1,
                                    theta=math.pi / 180,
                                    threshold=self.hough_thresholdR,
                                    param1=0,
                                    param2=0)

        # Get vertical lines
        vertical_linesR = []
        for line in raw_linesR:
            if line[1] < self.vertical_thresholdR or \
               line[1] > math.pi - self.vertical_thresholdR:

                vertical_linesR.append((abs(line[0]), line[1]))

        # Group vertical lines
        vertical_line_groupsR = [
        ]  # A list of line groups which are each a line list
        for line in vertical_linesR:
            group_found = False
            for line_group in vertical_line_groupsR:

                if line_group_accept_test(line_group, line, self.max_range):
                    line_group.append(line)
                    group_found = True

            if not group_found:
                vertical_line_groupsR.append([line])

        # Average line groups into lines
        vertical_linesR = []
        for line_group in vertical_line_groupsR:
            rhos = map(lambda line: line[0], line_group)
            angles = map(lambda line: line[1], line_group)
            line = (sum(rhos) / len(rhos), circular_average(angles, math.pi))
            vertical_linesR.append(line)
        '''
        for red_line in vertical_linesR:
            print "Red Line:", red_line[0],", ",red_line[1]
        for green_line in vertical_linesG:
            print "Green Line:", green_line[0],", ",green_line[1]
        '''
        for red_line in vertical_linesR:
            for green_line in vertical_linesG[:]:
                if math.fabs(green_line[0] - red_line[0]) < self.GR_Threshold0 and \
                   math.fabs(green_line[1] - red_line[1]) < self.GR_Threshold1:
                    vertical_linesG.remove(green_line)

        for red_line in vertical_linesR:
            print "New Red Line:", red_line[0], ", ", red_line[1]
        for green_line in vertical_linesG:
            print "New Green VLine:", green_line[0], ", ", green_line[1]
        for green_line in horizontal_lines:
            print "New Green HLine:", green_line[0], ", ", green_line[1]

        if len(vertical_linesR) is 0:
            print "No Red Found"

        self.left_pole = None
        self.right_pole = None
        if len(vertical_linesR) is 2:
            roi = cv.GetImageROI(frame)
            width = roi[2]
            height = roi[3]
            self.left_pole = round(
                min(vertical_linesR[0][0], vertical_linesR[1][0]),
                2) - width / 2
            self.right_pole = round(
                max(vertical_linesR[0][0], vertical_linesR[1][0]),
                2) - width / 2
        # TODO: If one pole is seen, is it left or right pole?

        # Calculate planar distance r (assuming we are moving perpendicular to
        # the hedge)
        if self.left_pole and self.right_pole:
            theta = abs(self.left_pole - self.right_pole)
            self.r = 3 / math.tan(math.radians(theta / 2))
        else:
            self.r = None

        for i in range(len(vertical_linesR[:])):
            if vertical_linesR[i][1] > math.pi / 2:
                vertical_linesR[i] = (vertical_linesR[i][0],
                                      -(math.pi - vertical_linesR[i][1]))
                print "Line changed to ", vertical_linesR[i]
        for line in vertical_linesR:
            print line
            if line[1] > math.pi / 2:
                line = (line[0], math.pi - line[1])
                print "Line changed to ", line

        libvision.misc.draw_lines(Gframe, vertical_linesG)
        libvision.misc.draw_lines(Gframe, horizontal_lines)
        libvision.misc.draw_lines(Rframe, vertical_linesR)

        # there was a merge error, these 3 lines conflicted b/c your copy out of date

        for line in vertical_linesR:
            roi = cv.GetImageROI(frame)
            width = roi[2]
            height = roi[3]
            x = line[0] * math.cos(line[1])
            y = line[0] * math.sin(line[1])
            cv.Circle(Rframe, (int(x), int(y)), 5, (0, 255, 0), -1, 8, 0)
            if x > width or y > width or x < 0 or y < 0:
                print "Lost point  ", x

        svr.debug("Original", self.test_frame)
        svr.debug("Red", Rframe)
        svr.debug("Green", Gframe)
        svr.debug("Green Binary", Gbinary)