示例#1
0
def get_contours(frame, approx=True):
    """Get contours from an image
    :: iplimage -> CvSeq
    """
    # A workaround for OpenCV 2.0 crash on receiving a (nearly) black image
    nonzero = cv.CountNonZero(frame)
    logging.debug("Segmentation got an image with %d nonzero pixels", nonzero)
    if nonzero < 20 or nonzero > 10000:
        return []

    storage = cv.CreateMemStorage(0)
    # find the contours
    contours = cv.FindContours(frame, storage, cv.CV_RETR_LIST,
                               cv.CV_CHAIN_APPROX_SIMPLE)
    if contours is None:
        return []

    res = []
    while contours:
        if not approx:
            result = contours
        else:
            result = cv.ApproxPoly(contours, storage, cv.CV_POLY_APPROX_DP,
                                   cv.ArcLength(contours) * 0.02, 1)
        res.append(result)
        contours = contours.h_next()

    return res
示例#2
0
    def __init__(self, contours, index, depth):
        self.index = index  # used from other thread, so it knows to clear drawing surface on zero.
        self.depth = depth  # kinect depth level
        self.mem1 = cv.CreateMemStorage(0)
        self.mem2 = cv.CreateMemStorage(0)

        sizeof_contour = ctypes.sizeof(cv.Contour.CSTRUCT)

        self.poly1 = cv.ApproxPoly(  # pass1
            contours, sizeof_contour, self.mem1, cv.CV_POLY_APPROX_DP, 3.0, 1)
        #print('POLY1')
        self.poly2 = cv.ApproxPoly(  # pass2
            self.poly1, sizeof_contour, self.mem2, cv.CV_POLY_APPROX_DP, 20.0,
            1)
        #print('POLY2')
        self.total = self.poly2.total
示例#3
0
def get_mask_with_contour(img,
                          ret_img=False,
                          ret_cont=False,
                          with_init_mask=False,
                          cont_color=cv.RGB(255, 50, 50),
                          normalize=True,
                          skin_version=1,
                          strong=False):
    if normalize:
        img = normalize_rgb(img, aggressive=0.005)
    mask = skin_mask(img) if skin_version == 1 else skin_mask2(img)

    di_mask = image_empty_clone(mask)
    cv.Dilate(mask, di_mask)

    seqs = cv.FindContours(cv.CloneImage(di_mask), memory(),
                           cv.CV_RETR_EXTERNAL)

    c_img = image_empty_clone(mask)
    cv.DrawContours(c_img, seqs, 255, 255, 10, -1)

    er_img = image_empty_clone(c_img)
    cv.Erode(c_img, er_img, iterations=2)

    seqs = cv.FindContours(cv.CloneImage(er_img), memory(),
                           cv.CV_RETR_EXTERNAL)
    if not seqs:
        print "no areas"
        return img, None
    seqs = cv.ApproxPoly(seqs,
                         memory(),
                         cv.CV_POLY_APPROX_DP,
                         parameter=3,
                         parameter2=1)

    result = []
    if ret_img:
        #        er_seq_img = cv.CreateImage(sizeOf(er_img), 8, 3)
        #        cv.Zero(er_seq_img)
        er_seq_img = cv.CloneImage(img)
        if with_init_mask:
            cv.Merge(mask, mask, mask, None, er_seq_img)

        if strong:
            cv.DrawContours(er_seq_img, seqs, cont_color, 0, 10, thickness=3)
            cv.DrawContours(er_seq_img,
                            seqs,
                            cv.RGB(0, 0, 0),
                            0,
                            10,
                            thickness=1)
        else:
            cv.DrawContours(er_seq_img, seqs, cont_color, 0, 10, thickness=1)
        result.append(er_seq_img)

    if ret_cont:
        result.append(seqs)

    return result
示例#4
0
 def _get_approx(self, conts):
     '''
     Returns contur aproximation
     @param conts: conturs
     '''
     per = cv.ArcLength(conts)
     conts = cv.ApproxPoly(conts, cv.CreateMemStorage(),
                           cv.CV_POLY_APPROX_DP, per * 0.05)
     #cv.DrawContours(self.img, conts, (0,0,255), (0,255,0), 4)
     return list(conts)
示例#5
0
    def detect_outline(self, image, threshold=THRESHOLD):
        img_size = cv.GetSize(image)
        grayscale = cv.CreateImage(img_size, 8, 1)
        cv.CvtColor(image, grayscale, cv.CV_BGR2GRAY)
        cv.EqualizeHist(grayscale, grayscale)

        storage = cv.CreateMemStorage(0)
        cv.Threshold(grayscale, grayscale, threshold, 255, cv.CV_THRESH_BINARY)
        contours = cv.FindContours(grayscale, cv.CreateMemStorage(),
                                   cv.CV_RETR_TREE, cv.CV_CHAIN_APPROX_SIMPLE)

        if len(contours) > 0:
            return cv.ApproxPoly(contours, storage, cv.CV_POLY_APPROX_DP, 1.5, 1)
        return contours
示例#6
0
文件: im.py 项目: ahmetech/breakout
def find_contours(im):
    """ @param im IplImage: an input gray image
        @return cvseq contours using cv.FindContours
    """
    storage = cv.CreateMemStorage(0)
    try:
      contours = cv.FindContours(im, 
                               storage,
                               cv.CV_RETR_TREE,
                               cv.CV_CHAIN_APPROX_SIMPLE)
      contours = cv.ApproxPoly(contours,
                             storage,
                             cv.CV_POLY_APPROX_DP, 3, 1)
    except cv.error, e:
      print e
      return None
示例#7
0
def motion_bbox(output, motion):
    #global muestra, prom
    global bbox_list
    #INICIO = time.time()
    contour = cv.FindContours(motion, mem_storage, cv.CV_RETR_CCOMP,
                              cv.CV_CHAIN_APPROX_SIMPLE)
    bbox_list = []  #lista para almacenar los bounding box de las manchas
    average_box_area = 0  #variable para obtener el area en promedio de las bounding box
    while contour:  #recorrido de los contornos/manchas
        bbox = cv.BoundingRect(
            list(contour))  #obtencion del bounding box del contorno actual
        pt1 = (bbox[0], bbox[1])  #punto 1 del bounding box
        pt2 = (bbox[0] + bbox[2], bbox[1] + bbox[3])  #punto 2 del bounding box
        w, h = abs(pt1[0] - pt2[0]), abs(
            pt1[1] - pt2[1])  #ancho y largo del bounding box
        #obtencion de puntos del contorno para crear un wire-frame
        polygon_points = cv.ApproxPoly(list(contour), mem_storage,
                                       cv.CV_POLY_APPROX_DP)
        #mostrar o las manchas de movimiento
        if SHOW_MOVEMENT_AREA:
            cv.FillPoly(output, [
                list(polygon_points),
            ], cv.CV_RGB(255, 255, 255), 0, 0)
        #mostrar o no los contornos de las manchas de movimiento
        if SHOW_MOVEMENT_CONTOUR and w * h > AREA * MIN_PERCENT:
            cv.PolyLine(output, [
                polygon_points,
            ], 0, cv.CV_RGB(255, 255, 255), 1, 0, 0)
        average_box_area += w * h  #acumulacion de totales de areas
        bbox_list.append((pt1, pt2))  #lista con todos los bounding box
        contour = contour.h_next()  #lectura del siguiente contorno, si hay
    if len(bbox_list) > 0:  #si hubo movimiento
        average_box_area = average_box_area / float(
            len(bbox_list))  #area promedio de bounding box
        new_bbox_list = [
        ]  #nueva lista de bounding box, eliminando los menores al area promedio
        for i in range(len(bbox_list)):  #recorrido de los bounding box
            pt1, pt2 = bbox_list[i]  #separacion en dos puntos del bounding box
            w, h = abs(pt1[0] - pt2[0]), abs(
                pt1[1] - pt2[1])  #obtencion del ancho y largo
            if w * h >= average_box_area and w * h > AREA * MIN_PERCENT:  #comparacion del area del bounding box con el promedio
                new_bbox_list.append(
                    (pt1,
                     pt2))  #si es mayor o igual, se queda en la nueva lista
    bbox_list = get_collided_bboxes(
        new_bbox_list
    )  #combinacion de varios bounding box en uno si estan en contacto
示例#8
0
    def __refresh_poly(self):
        self.polys_out = cv.ApproxPoly(self.contours, self.a_storage, cv.CV_POLY_APPROX_DP, self.__poly_acc / 100.0, -1)

        # Prints a count of the number of polygons and points in the picture thingy
        con = self.polys_out
        self.pointc = 0
        self.polyc = 0
        while not con == None:
            self.pointc += len(con)
            self.polyc += 1
            con = con.h_next()
        print '\n%d polygons'%self.polyc
        print '%d points'%self.pointc

        cv.Set(self.contour_out, cv.ScalarAll(255))
        cv.DrawContours(self.contour_out, self.polys_out, cv.Scalar(0, 0, 0), cv.Scalar(0, 0, 0), 99)

        cv.ShowImage('Contours', self.contour_out)
示例#9
0
def find_squares_from_binary( gray ):
    """
    use contour search to find squares in binary image
    returns list of numpy arrays containing 4 points
    """
    squares = []
    storage = cv.CreateMemStorage(0)
    contours = cv.FindContours(gray, storage, cv.CV_RETR_TREE, cv.CV_CHAIN_APPROX_SIMPLE, (0,0))  
    storage = cv.CreateMemStorage(0)
    while contours:
        #approximate contour with accuracy proportional to the contour perimeter
        arclength = cv.ArcLength(contours)
        polygon = cv.ApproxPoly( contours, storage, cv.CV_POLY_APPROX_DP, arclength * 0.02, 0)
        if is_square(polygon):
            squares.append(polygon[0:4])
        contours = contours.h_next()

    return squares
示例#10
0
    def get_candidates(self, m_d):
        '''
        Get candidates for this corner from new image
        @param m_d: marker_detector
        '''
        # if this corner is wider then MAX_CORNER_ANGLE, we probably won't
        # find it anyway. Instead lets find narrow corners and calculate its
        # position
        if self.angle > MAX_CORNER_ANGLE: return []
        cr = self.get_rectangle(m_d)
        cr = correct_rectangle(cr, m_d.size)
        if cr is None: return []
        m_d.set_ROI(cr)
        tmp_img = m_d.tmp_img
        gray_img = m_d.gray_img
        bw_img = m_d.bw_img
        canny = m_d.canny_img
        cv.Copy(gray_img, tmp_img)
        cv.Threshold(gray_img, bw_img, 125, 255, cv.CV_THRESH_OTSU)
        if self.black_inside > 0:
            cv.Not(bw_img, bw_img)
        cv.Canny(gray_img, canny, 300, 500)
        cv.Or(bw_img, canny, bw_img)
        tmpim = m_d.canny_img
        cv.Copy(bw_img, tmpim)
        cv.Set2D(tmpim, 1, 1, 255)
        conts = cv.FindContours(tmpim, cv.CreateMemStorage(),
                                cv.CV_RETR_EXTERNAL)
        cv.Zero(tmpim)
        m_d.set_ROI()
        cv.SetImageROI(tmpim, cr)
        result = []
        while conts:
            aconts = cv.ApproxPoly(conts, cv.CreateMemStorage(),
                                   cv.CV_POLY_APPROX_DP, 2)
            nconts = list(aconts)
            cv.PolyLine(tmpim, [nconts], True, (255, 255, 255))
            self._append_candidates_from_conts(cr, result, nconts, m_d)
            conts = conts.h_next()


#        print result
#        db.show([tmpim,m_d.draw_img], 'tmpim', 0, 0, 0)
        return result
示例#11
0
def get_contours(frame):
    """Get contours from an image
    :: iplimage -> CvSeq
    """
    storage = cv.CreateMemStorage(0)
    # find the contours
    contours = cv.FindContours( frame,
                                storage,
                                cv.CV_RETR_LIST,
                                cv.CV_CHAIN_APPROX_SIMPLE )
    if contours is None:
        return

    contours = cv.ApproxPoly( contours,
                              storage,
                              cv.CV_POLY_APPROX_DP,
                              cv.ArcLength(contours)*0.05,
                              1 )
    return contours
示例#12
0
def contours(mask):
    """ Return clockwise contours 
        (anticlockwise around holes) 
    """
    import cv
    storage = cv.CreateMemStorage()
    
    cont = cv.FindContours(cv.fromarray(mask.astype('uint8')),storage)    
    if not len(cont): 
        return [ ]
    
    approx = cv.ApproxPoly(cont,storage,cv.CV_POLY_APPROX_DP,1.0, 1)

    item = approx
    result = [ ]
    while item:
        assert item.v_next() is None and item.v_prev() is None
        result.append( list(item) )
        item = item.h_next()
    return result
示例#13
0
文件: track.py 项目: Edsby/track
    boundingBoxList = []

    # Use the white pixels as the motion and find the contours
    contour = cv.FindContours(greyImage, memStorage, cv.CV_RETR_CCOMP,
                              cv.CV_CHAIN_APPROX_SIMPLE)

    while contour:

        boundingRect = cv.BoundingRect(list(contour))
        p1 = (boundingRect[0], boundingRect[1])
        p2 = (boundingRect[0] + boundingRect[2],
              boundingRect[1] + boundingRect[3])

        boundingBoxList.append((p1, p2))
        polygonPoints = cv.ApproxPoly(list(contour), memStorage,
                                      cv.CV_POLY_APPROX_DP)

        #Show the contours
        cv.FillPoly(greyImage, [
            list(polygonPoints),
        ], cv.CV_RGB(255, 255, 255), 0, 0)
        cv.PolyLine(displayImage, [
            polygonPoints,
        ], 0, cv.CV_RGB(255, 255, 255), 1, 0, 0)

        contour = contour.h_next()

    # Find the average size of the bounding box targets and remove ones that are 5% or less than the average as noise
    boxAreas = []
    for box in boundingBoxList:
        boxWidth = box[right][0] - box[left][0]
def shapeAnalysis(mask):

    height, width = mask.shape
    pixels = height * width

    # spatial and central moments
    moments = cv.Moments(mask, binary=1)
    huMoments = cv.GetHuMoments(moments)
    print "Shape hu moments", huMoments

    # distances from the gravity point
    contour_seq = cv.FindContours(np.array(mask), cv.CreateMemStorage(),
                                  cv.CV_RETR_TREE, cv.CV_CHAIN_APPROX_SIMPLE)
    gravity_center = (int(moments.m10 / moments.m00),
                      int(moments.m01 / moments.m00))  # (x, y)
    gx, gy = gravity_center
    distances = np.array(
        [math.sqrt((gx - x)**2 + (gy - y)**2) for (x, y) in contour_seq])
    dist_distri, bin_dist = np.histogram(distances,
                                         bins=10,
                                         range=None,
                                         normed=True)
    print "dist distribution", dist_distri
    dist_max = np.max(distances)
    dist_min = np.min(distances)
    dist_ratio_min_max = dist_min / dist_max
    print "dist ratio min max", dist_ratio_min_max
    dist_mean = np.mean(distances)
    dist_std = np.std(distances)

    # normalize distance min and max
    dist_max = dist_max / pixels
    dist_min = dist_min / pixels
    dist_mean = dist_mean / pixels
    dist_std = dist_std / pixels
    print "dist max", dist_max
    print "dist min", dist_min
    print "dist mean", dist_mean
    print "dist std", dist_std

    # number of petals
    nbPetals = np.sum([
        min(x1, x2) < dist_mean < max(x1, x2)
        for x1, x2 in zip(distances[:-1], distances[1:])
    ]) / 2
    print "petals", nbPetals

    poly_seq = cv.ApproxPoly(contour_seq, cv.CreateMemStorage(),
                             cv.CV_POLY_APPROX_DP, 2.8)
    ppimg = np.zeros(mask.shape)
    for (x, y) in poly_seq:
        ppimg[y, x] = 255
    imsave('/home/cplab/workspace/imageex/src/imageex/static/POLYYYAAAAA.png',
           ppimg)

    convex_hull = cv.ConvexHull2(poly_seq, cv.CreateMemStorage())
    convexity_defects = cv.ConvexityDefects(poly_seq, convex_hull,
                                            cv.CreateMemStorage())

    # number of defects
    nbDefects = len(convexity_defects)
    print "defects", nbDefects

    convexity_seq = sum([[cd[0], cd[2], cd[1]] for cd in convexity_defects],
                        [])
    ppimg = np.zeros(mask.shape)
    for (x, y) in convexity_seq:
        ppimg[y, x] = 255
    imsave('/home/cplab/workspace/imageex/src/imageex/static/CONVEXXAAAAA.png',
           ppimg)

    convexity_depths = np.array([cd[3] for cd in convexity_defects])
    convexity_depth_max = np.max(convexity_depths)
    convexity_depth_min = np.min(convexity_depths)
    convexity_depth_ratio_min_max = convexity_depth_min / convexity_depth_max
    print "convexity depth ratio min max", convexity_depth_ratio_min_max

    #normalize
    convexity_depth_max = convexity_depth_max / pixels

    print "convexity depth max", convexity_depth_max

    area = cv.ContourArea(contour_seq)
    perimeter = cv.ArcLength(contour_seq)
    perimeterOarea = perimeter / area
    print "perimeter over area", perimeterOarea

    features = []
    features += list(huMoments)
    features += dist_distri, dist_ratio_min_max, dist_max, dist_min, dist_mean, dist_std
    features += nbPetals, nbDefects
    features += convexity_depth_ratio_min_max, convexity_depth_max, perimeterOarea

    return features
示例#15
0
    def find_better_point(self, from_, direction, predicted_length, range=20):
        '''
        Tries to find better corner arm - goes from from_ using vector direction
        on a line to find last visible point on this line
        @param from_:
        @param tpredicted_length: predicted length of this side
        @param direction:
        '''
        img = self.bw_img
        timg = self.tmp_img
        L1 = predicted_length * 1.2
        vec = direction
        L2 = length(vec)
        vec = add((0, 0), vec, L1 / L2) #vector towards direction of length of old side
        vec1 = rotateVec(vec, d2r(range))
        vec2 = rotateVec(vec, d2r(-range))
        x, y = from_
        cv.ResetImageROI(img)
        size = cv.GetSize(img)

        border_points = [add(from_, vec1), add(from_, vec2), (x - 5, y - 5), (x + 5, y + 5)]
        (x, y, wx, wy) = cv.BoundingRect(border_points)
        crect = correct_rectangle((x - 3, y - 3, wx + 6, wy + 6), size)
        [cv.SetImageROI(i, crect) for i in [img, timg, self.gray_img]]
        self.bounds.extend(cvrect(crect))
        cv.Threshold(self.gray_img, img, 125, 255, cv.CV_THRESH_OTSU)
        cv.Not(img, timg)
        cv.Canny(self.gray_img, img, 300, 500)
        cv.Or(img, timg,timg)
        rect = cvrect(crect)
        cv.Set2D(timg, 1, 1, (30, 30, 30))
        conts = cv.FindContours(timg, cv.CreateMemStorage(), cv.CV_RETR_EXTERNAL)
        db.DrawContours(timg, conts, (255, 255, 255), (128, 128, 128), 10)
        cv.Zero(timg)
        fr = add(from_, rect[0], -1)
        ans = []
        while conts:
            cont = cv.ApproxPoly(conts, cv.CreateMemStorage(), cv.CV_POLY_APPROX_DP, parameter=2, parameter2=0)
            cv.DrawContours(timg, cont, (255, 255, 255), (128, 128, 128), 10)
            cont = list(cont)
            L = len(cont)
            for i, p in enumerate(cont):
                if length(vector(fr, p)) < 5:
                    prev = cont[(i - 1 + L) % L]
                    next = cont[(i + 1) % L]
                    ans.append(vector(fr, prev))
                    ans.append(vector(fr, next))
            conts = conts.h_next()
        [cv.ResetImageROI(i) for i in [self.gray_img, timg, img]]
        if len(ans) == 0:
            # we didn't find corresponding corner,
            # that means it wasn't really a corner
            return None
        if len(ans) == 2 and ans[0] == ans[1]: return add(from_, direction)
        min = math.pi
        min_index = 0
        for i, v in enumerate(ans):
            tmp = vectorAngle(vec, v)
            if tmp < min:
                min = tmp
                min_index = i

        ans = ans[min_index]

        if length(ans)+1< L2:
            # the point we just found is closer then the previous one
            return add(from_,direction)

        abs_point = add(from_, ans)
        if point_on_edge(abs_point, crect):
            if not point_on_edge(abs_point, (0, 0, size[0], size[1])):
                if range < 20:
                    # this is recurence call. When we are here it means that
                    # side is longer then expected by over 2 times - it is not
                    # the side we are looking for- corner is not valid
                    return None
                else:
                    return self.find_better_point(from_, abs_point,
                                                  predicted_length * 2, 5)

        return abs_point
示例#16
0
    def run(self):
        global centroid
        frame = cv.QueryFrame(self.capture)
        while not frame:
            cv.WaitKey(10)
            frame = cv.QueryFrame(self.capture)

        frame_size = cv.GetSize(frame)

        # Capture the first frame from webcam for image properties
        display_image = cv.QueryFrame(self.capture)

        while not display_image:
            cv.WaitKey(10)
            display_image = cv.QueryFrame(self.capture)

        # Greyscale image, thresholded to create the motion mask:
        grey_image = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_8U, 1)

        # The RunningAvg() function requires a 32-bit or 64-bit image...
        running_average_image = cv.CreateImage(cv.GetSize(frame),
                                               cv.IPL_DEPTH_32F, 3)
        # ...but the AbsDiff() function requires matching image depths:
        running_average_in_display_color_depth = cv.CloneImage(display_image)

        # RAM used by FindContours():
        mem_storage = cv.CreateMemStorage(0)

        # The difference between the running average and the current frame:
        difference = cv.CloneImage(display_image)

        target_count = 1
        last_target_count = 1
        last_target_change_t = 0.0
        k_or_guess = 1
        codebook = []
        frame_count = 0
        last_frame_entity_list = []

        t0 = time.time()

        # For toggling display:
        image_list = ["camera", "difference", "threshold", "display", "faces"]
        image_index = 0  # Index into image_list

        # Prep for text drawing:
        text_font = cv.InitFont(cv.CV_FONT_HERSHEY_COMPLEX, .5, .5, 0.0, 1,
                                cv.CV_AA)
        text_coord = (5, 15)
        text_color = cv.CV_RGB(255, 255, 255)

        ###############################
        ### Face detection stuff
        haar_cascade = cv.Load('haarcascades/haarcascade_frontalface_alt.xml')

        # Set this to the max number of targets to look for (passed to k-means):
        max_targets = 3

        while True:

            # Capture frame from webcam
            camera_image = cv.QueryFrame(self.capture)

            while not camera_image:
                cv.WaitKey(10)
                camera_image = cv.QueryFrame(self.capture)

            frame_count += 1
            print 'frame_count = ', frame_count
            frame_t0 = time.time()

            # Create an image with interactive feedback:
            display_image = cv.CloneImage(camera_image)

            # Create a working "color image" to modify / blur
            color_image = cv.CloneImage(display_image)

            # Smooth to get rid of false positives
            cv.Smooth(color_image, color_image, cv.CV_GAUSSIAN, 19, 0)

            # Use the Running Average as the static background
            # a = 0.020 leaves artifacts lingering way too long.
            # a = 0.320 works well at 320x240, 15fps.  (1/a is roughly num frames.)
            cv.RunningAvg(color_image, running_average_image, 0.320, None)

            # Convert the scale of the moving average.
            cv.ConvertScale(running_average_image,
                            running_average_in_display_color_depth, 1.0, 0.0)

            # Subtract the current frame from the moving average.
            cv.AbsDiff(color_image, running_average_in_display_color_depth,
                       difference)

            # Convert the image to greyscale.
            cv.CvtColor(difference, grey_image, cv.CV_RGB2GRAY)

            # Threshold the image to a black and white motion mask:
            cv.Threshold(grey_image, grey_image, 2, 255, cv.CV_THRESH_BINARY)
            # Smooth and threshold again to eliminate "sparkles"
            cv.Smooth(grey_image, grey_image, cv.CV_GAUSSIAN, 19, 0)
            cv.Threshold(grey_image, grey_image, 240, 255, cv.CV_THRESH_BINARY)

            grey_image_as_array = numpy.asarray(cv.GetMat(grey_image))
            non_black_coords_array = numpy.where(grey_image_as_array > 3)
            # Convert from numpy.where()'s two separate lists to one list of (x, y) tuples:
            non_black_coords_array = zip(non_black_coords_array[1],
                                         non_black_coords_array[0])

            points = [
            ]  # Was using this to hold either pixel coords or polygon coords.
            bounding_box_list = []

            # Now calculate movements using the white pixels as "motion" data
            contour = cv.FindContours(grey_image, mem_storage,
                                      cv.CV_RETR_CCOMP,
                                      cv.CV_CHAIN_APPROX_SIMPLE)

            while contour:

                bounding_rect = cv.BoundingRect(list(contour))
                point1 = (bounding_rect[0], bounding_rect[1])
                point2 = (bounding_rect[0] + bounding_rect[2],
                          bounding_rect[1] + bounding_rect[3])

                bounding_box_list.append((point1, point2))
                polygon_points = cv.ApproxPoly(list(contour), mem_storage,
                                               cv.CV_POLY_APPROX_DP)

                # To track polygon points only (instead of every pixel):
                #points += list(polygon_points)

                # Draw the contours:
                ###cv.DrawContours(color_image, contour, cv.CV_RGB(255,0,0), cv.CV_RGB(0,255,0), levels, 3, 0, (0,0) )
                cv.FillPoly(grey_image, [
                    list(polygon_points),
                ], cv.CV_RGB(255, 255, 255), 0, 0)
                cv.PolyLine(display_image, [
                    polygon_points,
                ], 0, cv.CV_RGB(255, 255, 255), 1, 0, 0)
                #cv.Rectangle( display_image, point1, point2, cv.CV_RGB(120,120,120), 1)

                contour = contour.h_next()

            # Find the average size of the bbox (targets), then
            # remove any tiny bboxes (which are prolly just noise).
            # "Tiny" is defined as any box with 1/10th the area of the average box.
            # This reduces false positives on tiny "sparkles" noise.
            box_areas = []
            for box in bounding_box_list:
                box_width = box[right][0] - box[left][0]
                box_height = box[bottom][0] - box[top][0]
                box_areas.append(box_width * box_height)

                #cv.Rectangle( display_image, box[0], box[1], cv.CV_RGB(255,0,0), 1)

            average_box_area = 0.0
            if len(box_areas):
                average_box_area = float(sum(box_areas)) / len(box_areas)

            trimmed_box_list = []
            for box in bounding_box_list:
                box_width = box[right][0] - box[left][0]
                box_height = box[bottom][0] - box[top][0]

                # Only keep the box if it's not a tiny noise box:
                if (box_width * box_height) > average_box_area * 0.1:
                    trimmed_box_list.append(box)

            # Draw the trimmed box list:
            bounding_box_list = merge_collided_bboxes(trimmed_box_list)

            # Draw the merged box list:
            for box in bounding_box_list:
                cv.Rectangle(display_image, box[0], box[1],
                             cv.CV_RGB(0, 255, 0), 1)

            # Here are our estimate points to track, based on merged & trimmed boxes:
            estimated_target_count = len(bounding_box_list)

            # Don't allow target "jumps" from few to many or many to few.
            # Only change the number of targets up to one target per n seconds.
            # This fixes the "exploding number of targets" when something stops moving
            # and the motion erodes to disparate little puddles all over the place.

            if frame_t0 - last_target_change_t < .350:  # 1 change per 0.35 secs
                estimated_target_count = last_target_count
            else:
                if last_target_count - estimated_target_count > 1:
                    estimated_target_count = last_target_count - 1
                if estimated_target_count - last_target_count > 1:
                    estimated_target_count = last_target_count + 1
                last_target_change_t = frame_t0

            # Clip to the user-supplied maximum:
            estimated_target_count = min(estimated_target_count, max_targets)

            # The estimated_target_count at this point is the maximum number of targets
            # we want to look for.  If kmeans decides that one of our candidate
            # bboxes is not actually a target, we remove it from the target list below.

            # Using the numpy values directly (treating all pixels as points):
            points = non_black_coords_array
            center_points = []

            if len(points):

                # If we have all the "target_count" targets from last frame,
                # use the previously known targets (for greater accuracy).
                k_or_guess = max(estimated_target_count,
                                 1)  # Need at least one target to look for.
                if len(codebook) == estimated_target_count:
                    k_or_guess = codebook

                #points = vq.whiten(array( points ))  # Don't do this!  Ruins everything.
                codebook, distortion = vq.kmeans(array(points), k_or_guess)

                # Convert to tuples (and draw it to screen)
                for center_point in codebook:
                    center_point = (int(center_point[0]), int(center_point[1]))
                    center_points.append(center_point)
                    #cv.Circle(display_image, center_point, 10, cv.CV_RGB(255, 0, 0), 2)
                    #cv.Circle(display_image, center_point, 5, cv.CV_RGB(255, 0, 0), 3)

            # Now we have targets that are NOT computed from bboxes -- just
            # movement weights (according to kmeans).  If any two targets are
            # within the same "bbox count", average them into a single target.
            #
            # (Any kmeans targets not within a bbox are also kept.)

            trimmed_center_points = []
            removed_center_points = []

            for box in bounding_box_list:
                # Find the centers within this box:
                center_points_in_box = []

                for center_point in center_points:
                    if  center_point[0] < box[right][0] and center_point[0] > box[left][0] and \
                        center_point[1] < box[bottom][1] and center_point[1] > box[top][1] :

                        # This point is within the box.
                        center_points_in_box.append(center_point)

                # Now see if there are more than one.  If so, merge them.
                if len(center_points_in_box) > 1:
                    # Merge them:
                    x_list = y_list = []
                    for point in center_points_in_box:
                        x_list.append(point[0])
                        y_list.append(point[1])

                    average_x = int(float(sum(x_list)) / len(x_list))
                    average_y = int(float(sum(y_list)) / len(y_list))

                    trimmed_center_points.append((average_x, average_y))

                    # Record that they were removed:
                    removed_center_points += center_points_in_box

                if len(center_points_in_box) == 1:
                    trimmed_center_points.append(
                        center_points_in_box[0])  # Just use it.

            # If there are any center_points not within a bbox, just use them.
            # (It's probably a cluster comprised of a bunch of small bboxes.)
            for center_point in center_points:
                if (not center_point in trimmed_center_points) and (
                        not center_point in removed_center_points):
                    trimmed_center_points.append(center_point)

            # Determine if there are any new (or lost) targets:
            actual_target_count = len(trimmed_center_points)
            last_target_count = actual_target_count

            # Now build the list of physical entities (objects)
            this_frame_entity_list = []

            # An entity is list: [ name, color, last_time_seen, last_known_coords ]
            for target in trimmed_center_points:
                # Is this a target near a prior entity (same physical entity)?
                entity_found = False
                entity_distance_dict = {}

                for entity in last_frame_entity_list:

                    entity_coords = entity[3]
                    delta_x = entity_coords[0] - target[0]
                    delta_y = entity_coords[1] - target[1]

                    distance = sqrt(pow(delta_x, 2) + pow(delta_y, 2))
                    entity_distance_dict[distance] = entity

                # Did we find any non-claimed entities (nearest to furthest):
                distance_list = entity_distance_dict.keys()
                distance_list.sort()

                for distance in distance_list:
                    # Yes; see if we can claim the nearest one:
                    nearest_possible_entity = entity_distance_dict[distance]

                    # Don't consider entities that are already claimed:
                    if nearest_possible_entity in this_frame_entity_list:
                        #print "Target %s: Skipping the one iwth distance: %d at %s, C:%s" % (target, distance, nearest_possible_entity[3], nearest_possible_entity[1] )
                        continue

                    #print "Target %s: USING the one iwth distance: %d at %s, C:%s" % (target, distance, nearest_possible_entity[3] , nearest_possible_entity[1])
                    # Found the nearest entity to claim:
                    entity_found = True
                    nearest_possible_entity[
                        2] = frame_t0  # Update last_time_seen
                    nearest_possible_entity[
                        3] = target  # Update the new location
                    this_frame_entity_list.append(nearest_possible_entity)
                    #log_file.write( "%.3f MOVED %s %d %d\n" % ( frame_t0, nearest_possible_entity[0], nearest_possible_entity[3][0], nearest_possible_entity[3][1]  ) )
                    break

                if entity_found == False:
                    # It's a new entity.
                    color = (random.randint(0, 255), random.randint(0, 255),
                             random.randint(0, 255))
                    name = hashlib.md5(str(frame_t0) +
                                       str(color)).hexdigest()[:6]
                    last_time_seen = frame_t0

                    new_entity = [name, color, last_time_seen, target]
                    this_frame_entity_list.append(new_entity)
                    #log_file.write( "%.3f FOUND %s %d %d\n" % ( frame_t0, new_entity[0], new_entity[3][0], new_entity[3][1]  ) )

            # Now "delete" any not-found entities which have expired:
            entity_ttl = 1.0  # 1 sec.

            for entity in last_frame_entity_list:
                last_time_seen = entity[2]
                if frame_t0 - last_time_seen > entity_ttl:
                    # It's gone.
                    #log_file.write( "%.3f STOPD %s %d %d\n" % ( frame_t0, entity[0], entity[3][0], entity[3][1]  ) )
                    pass
                else:
                    # Save it for next time... not expired yet:
                    this_frame_entity_list.append(entity)

            # For next frame:
            last_frame_entity_list = this_frame_entity_list

            # Draw the found entities to screen:
            for entity in this_frame_entity_list:
                center_point = entity[3]
                c = entity[1]  # RGB color tuple
                cv.Circle(display_image, center_point, 20,
                          cv.CV_RGB(c[0], c[1], c[2]), 1)
                cv.Circle(display_image, center_point, 15,
                          cv.CV_RGB(c[0], c[1], c[2]), 1)
                cv.Circle(display_image, center_point, 10,
                          cv.CV_RGB(c[0], c[1], c[2]), 2)
                cv.Circle(display_image, center_point, 5,
                          cv.CV_RGB(c[0], c[1], c[2]), 3)

            #print "min_size is: " + str(min_size)
            # Listen for ESC or ENTER key
            c = cv.WaitKey(7) % 0x100
            if c == 27 or c == 10:
                break

            # Toggle which image to show
            if chr(c) == 'd':
                image_index = (image_index + 1) % len(image_list)

            image_name = image_list[image_index]
            image_name = "display"
            # for black and white: Threshold
            #for colored = display

            # Display frame to user
            if image_name == "camera":
                image = camera_image
                cv.PutText(image, "Camera (Normal)", text_coord, text_font,
                           text_color)
            elif image_name == "difference":
                image = difference
                cv.PutText(image, "Difference Image", text_coord, text_font,
                           text_color)
            elif image_name == "display":
                image = display_image
                cv.PutText(image, "Targets (w/AABBs and contours)", text_coord,
                           text_font, text_color)
            elif image_name == "threshold":
                # Convert the image to color.
                cv.CvtColor(grey_image, display_image, cv.CV_GRAY2RGB)
                image = display_image  # Re-use display image here
                cv.PutText(image, "Motion Mask", text_coord, text_font,
                           text_color)
            elif image_name == "faces":
                # Do face detection
                detect_faces(camera_image, haar_cascade, mem_storage)
                image = camera_image  # Re-use camera image here
                cv.PutText(image, "Face Detection", text_coord, text_font,
                           text_color)

            cv.ShowImage("Target", image)

            if self.writer:
                cv.WriteFrame(self.writer, image)

            arr = numpy.asarray(image[:, :])
            move_thresh = 100
            counter = 0

            # If only using a camera, then there is no time.sleep() needed,
            # because the camera clips us to 15 fps.  But if reading from a file,
            # we need this to keep the time-based target clipping correct:
            frame_t1 = time.time()

            centroid = get_centroid(trimmed_center_points)
            print 'centroid = ', centroid

            # If reading from a file, put in a forced delay:
            if not self.writer:
                delta_t = frame_t1 - frame_t0
                if delta_t < (1.0 / 15.0): time.sleep((1.0 / 15.0) - delta_t)

        t1 = time.time()
        time_delta = t1 - t0
        processed_fps = float(frame_count) / time_delta
        print "Got %d frames. %.1f s. %f fps." % (frame_count, time_delta,
                                                  processed_fps)
示例#17
0
    def run(self):
        frame = cv.QueryFrame(self.capture)
        frame_size = cv.GetSize(frame)

        # Capture the first frame from webcam for image properties
        display_image = cv.QueryFrame(self.capture)

        # Greyscale image, thresholded to create the motion mask:
        grey_image = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_8U, 1)

        # The RunningAvg() function requires a 32-bit or 64-bit image...
        running_average_image = cv.CreateImage(cv.GetSize(frame),
                                               cv.IPL_DEPTH_32F, 3)
        # ...but the AbsDiff() function requires matching image depths:
        running_average_in_display_color_depth = cv.CloneImage(display_image)

        # RAM used by FindContours():
        mem_storage = cv.CreateMemStorage(0)

        # The difference between the running average and the current frame:
        difference = cv.CloneImage(display_image)

        target_count = 1
        last_target_count = 1
        last_target_change_t = 0.0
        k_or_guess = 1
        codebook = []
        frame_count = 0
        last_frame_entity_list = []

        t0 = time.time()

        # For toggling display:
        image_list = ["display", "difference", "threshold", "camera", "faces"]
        image_index = 0  # Index into image_list

        # Prep for text drawing:
        text_font = cv.InitFont(cv.CV_FONT_HERSHEY_COMPLEX, .5, .5, 0.0, 1,
                                cv.CV_AA)
        text_coord = (5, 15)
        text_color = cv.CV_RGB(255, 255, 255)

        haar_cascade = cv.Load(
            '/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml'
        )

        max_targets = 3

        while True:

            camera_image = cv.QueryFrame(self.capture)

            frame_count += 1
            frame_t0 = time.time()

            # Create an image with interactive feedback:
            display_image = cv.CloneImage(camera_image)

            # Create a working "color image" to modify / blur
            color_image = cv.CloneImage(display_image)

            # Smooth to get rid of false positives
            cv.Smooth(color_image, color_image, cv.CV_GAUSSIAN, 19, 0)

            # Use the Running Average as the static background
            # a = 0.020 leaves artifacts lingering way too long.
            # a = 0.320 works well at 320x240, 15fps.  (1/a is roughly num frames.)
            cv.RunningAvg(color_image, running_average_image, 0.420, None)

            # Convert the scale of the moving average.
            cv.ConvertScale(running_average_image,
                            running_average_in_display_color_depth, 1.0, 0.0)

            # Subtract the current frame from the moving average.
            cv.AbsDiff(color_image, running_average_in_display_color_depth,
                       difference)

            # Convert the image to greyscale.
            cv.CvtColor(difference, grey_image, cv.CV_RGB2GRAY)

            # Threshold the image to a black and white motion mask:
            cv.Threshold(grey_image, grey_image, 2, 255, cv.CV_THRESH_BINARY)
            # Smooth and threshold again to eliminate "sparkles"
            cv.Smooth(grey_image, grey_image, cv.CV_GAUSSIAN, 19, 0)
            cv.Threshold(grey_image, grey_image, 240, 255, cv.CV_THRESH_BINARY)
            cv.Dilate(grey_image, grey_image, None, 18)
            cv.Erode(grey_image, grey_image, None, 20)

            grey_image_as_array = numpy.asarray(cv.GetMat(grey_image))
            non_black_coords_array = numpy.where(grey_image_as_array > 3)
            # Convert from numpy.where()'s two separate lists to one list of (x, y) tuples:
            non_black_coords_array = zip(non_black_coords_array[1],
                                         non_black_coords_array[0])

            points = [
            ]  # Was using this to hold either pixel coords or polygon coords.
            bounding_box_list = []

            # Now calculate movements using the white pixels as "motion" data
            contour = cv.FindContours(grey_image, mem_storage,
                                      cv.CV_RETR_CCOMP,
                                      cv.CV_CHAIN_APPROX_SIMPLE)

            while contour:

                bounding_rect = cv.BoundingRect(list(contour))
                point1 = (bounding_rect[0], bounding_rect[1])
                point2 = (bounding_rect[0] + bounding_rect[2],
                          bounding_rect[1] + bounding_rect[3])

                bounding_box_list.append((point1, point2))
                polygon_points = cv.ApproxPoly(list(contour), mem_storage,
                                               cv.CV_POLY_APPROX_DP)

                # To track polygon points only (instead of every pixel):
                #points += list(polygon_points)

                # Draw the contours:
                levels = 0
                cv.DrawContours(color_image, contour, cv.CV_RGB(255, 0, 0),
                                cv.CV_RGB(0, 255, 0), levels, 3, 0, (0, 0))
                cv.FillPoly(grey_image, [
                    list(polygon_points),
                ], cv.CV_RGB(255, 255, 255), 0, 0)
                cv.PolyLine(display_image, [
                    polygon_points,
                ], 0, cv.CV_RGB(255, 255, 255), 1, 0, 0)
                #cv.Rectangle( display_image, point1, point2, cv.CV_RGB(120,120,120), 1)

                contour = contour.h_next()

            # Find the average size of the bbox (targets), then
            # remove any tiny bboxes (which are prolly just noise).
            # "Tiny" is defined as any box with 1/10th the area of the average box.
            # This reduces false positives on tiny "sparkles" noise.
            box_areas = []
            for box in bounding_box_list:
                box_width = box[right][0] - box[left][0]
                box_height = box[bottom][0] - box[top][0]
                box_areas.append(box_width * box_height)

                #cv.Rectangle( display_image, box[0], box[1], cv.CV_RGB(255,0,0), 1)

            average_box_area = 0.0
            if len(box_areas):
                average_box_area = float(sum(box_areas)) / len(box_areas)

            trimmed_box_list = []
            for box in bounding_box_list:
                box_width = box[right][0] - box[left][0]
                box_height = box[bottom][0] - box[top][0]

                # Only keep the box if it's not a tiny noise box:
                if (box_width * box_height) > average_box_area * 0.1:
                    trimmed_box_list.append(box)

            # Draw the trimmed box list:
            #for box in trimmed_box_list:
            #	cv.Rectangle( display_image, box[0], box[1], cv.CV_RGB(0,255,0), 2 )

            bounding_box_list = merge_collided_bboxes(trimmed_box_list)

            # Draw the merged box list:
            for box in bounding_box_list:
                cv.Rectangle(display_image, box[0], box[1],
                             cv.CV_RGB(0, 255, 0), 1)

            # Here are our estimate points to track, based on merged & trimmed boxes:
            estimated_target_count = len(bounding_box_list)

            if frame_t0 - last_target_change_t < .650:  # 1 change per 0.35 secs
                estimated_target_count = last_target_count
            else:
                if last_target_count - estimated_target_count > 1:
                    estimated_target_count = last_target_count - 1
                if estimated_target_count - last_target_count > 1:
                    estimated_target_count = last_target_count + 1
                last_target_change_t = frame_t0

            # Clip to the user-supplied maximum:
            estimated_target_count = min(estimated_target_count, max_targets)
            points = non_black_coords_array
            center_points = []

            if len(points):

                k_or_guess = max(estimated_target_count,
                                 1)  # Need at least one target to look for.
                if len(codebook) == estimated_target_count:
                    k_or_guess = codebook

                #points = vq.whiten(array( points ))  # Don't do this!  Ruins everything.
                codebook, distortion = vq.kmeans(array(points), k_or_guess)

                # Convert to tuples (and draw it to screen)
                for center_point in codebook:
                    center_point = (int(center_point[0]), int(center_point[1]))
                    center_points.append(center_point)
            trimmed_center_points = []
            removed_center_points = []

            for box in bounding_box_list:
                # Find the centers within this box:
                center_points_in_box = []

                for center_point in center_points:
                    if center_point[0] < box[right][0] and center_point[0] > box[left][0] and \
                     center_point[1] < box[bottom][1] and center_point[1] > box[top][1] :

                        # This point is within the box.
                        center_points_in_box.append(center_point)

                # Now see if there are more than one.  If so, merge them.
                if len(center_points_in_box) > 1:
                    # Merge them:
                    x_list = y_list = []
                    for point in center_points_in_box:
                        x_list.append(point[0])
                        y_list.append(point[1])

                    average_x = int(float(sum(x_list)) / len(x_list))
                    average_y = int(float(sum(y_list)) / len(y_list))

                    trimmed_center_points.append((average_x, average_y))

                    # Record that they were removed:
                    removed_center_points += center_points_in_box

                if len(center_points_in_box) == 1:
                    trimmed_center_points.append(
                        center_points_in_box[0])  # Just use it.

            # If there are any center_points not within a bbox, just use them.
            # (It's probably a cluster comprised of a bunch of small bboxes.)
            for center_point in center_points:
                if (not center_point in trimmed_center_points) and (
                        not center_point in removed_center_points):
                    trimmed_center_points.append(center_point)

            # Determine if there are any new (or lost) targets:
            actual_target_count = len(trimmed_center_points)
            last_target_count = actual_target_count

            # Now build the list of physical entities (objects)
            this_frame_entity_list = []

            # An entity is list: [ name, color, last_time_seen, last_known_coords ]

            for target in trimmed_center_points:

                # Is this a target near a prior entity (same physical entity)?
                entity_found = False
                entity_distance_dict = {}

                for entity in last_frame_entity_list:

                    entity_coords = entity[3]
                    delta_x = entity_coords[0] - target[0]
                    delta_y = entity_coords[1] - target[1]

                    distance = sqrt(pow(delta_x, 2) + pow(delta_y, 2))
                    entity_distance_dict[distance] = entity

                # Did we find any non-claimed entities (nearest to furthest):
                distance_list = entity_distance_dict.keys()
                distance_list.sort()

                for distance in distance_list:

                    # Yes; see if we can claim the nearest one:
                    nearest_possible_entity = entity_distance_dict[distance]

                    if nearest_possible_entity in this_frame_entity_list:
                        continue

                    # Found the nearest entity to claim:
                    entity_found = True
                    nearest_possible_entity[
                        2] = frame_t0  # Update last_time_seen
                    nearest_possible_entity[
                        3] = target  # Update the new location
                    this_frame_entity_list.append(nearest_possible_entity)
                    break

                if entity_found == False:
                    # It's a new entity.
                    color = (random.randint(0, 255), random.randint(0, 255),
                             random.randint(0, 255))
                    name = hashlib.md5(str(frame_t0) +
                                       str(color)).hexdigest()[:6]
                    last_time_seen = frame_t0

                    new_entity = [name, color, last_time_seen, target]
                    this_frame_entity_list.append(new_entity)

            # Now "delete" any not-found entities which have expired:
            entity_ttl = 1.0  # 1 sec.

            ent_count = 0
            for entity in last_frame_entity_list:
                last_time_seen = entity[2]
                if frame_t0 - last_time_seen > entity_ttl:
                    pass
                else:
                    # Save it for next time... not expired yet:
                    this_frame_entity_list.append(entity)
                    ent_count += 1

            # For next frame:
            last_frame_entity_list = this_frame_entity_list

            # Draw the found entities to screen:
            count = 0
            if ent_count != 0:
                entity = this_frame_entity_list[0]
                center_point = entity[3]
                c = entity[1]  # RGB color tuple
                # print '%s %d %d %d' % (entity[0], count, center_point[0], center_point[1])
                cv.Circle(display_image, center_point, 20,
                          cv.CV_RGB(c[0], c[1], c[2]), 1)
                cv.Circle(display_image, center_point, 15,
                          cv.CV_RGB(c[0], c[1], c[2]), 1)
                cv.Circle(display_image, center_point, 10,
                          cv.CV_RGB(c[0], c[1], c[2]), 2)
                cv.Circle(display_image, center_point, 5,
                          cv.CV_RGB(c[0], c[1], c[2]), 3)

            text_font = cv.InitFont(cv.CV_FONT_HERSHEY_COMPLEX, .5, .5, 0.0, 1,
                                    cv.CV_AA)
            text_coord = (5, 15)
            text_color = cv.CV_RGB(255, 255, 255)

            x = 50 + (center_point[0] * 80 / 320)
            y = 20 + (center_point[1] * 80 / 240)
            if self.have_eye:
                self.ServoMove(0, int(x))
                self.ServoMove(1, int(y))

            s = '%3.0d %3.0d' % (x, y)
            cv.PutText(display_image, str(s), text_coord, text_font,
                       text_color)

            #print "min_size is: " + str(min_size)
            # Listen for ESC or ENTER key
            c = cv.WaitKey(7) % 0x100
            if c == 27 or c == 10:
                break

            # Toggle which image to show
            if chr(c) == 'd':
                image_index = (image_index + 1) % len(image_list)

            image_name = image_list[image_index]

            # Display frame to user
            if image_name == "display":
                image = display_image

# cv.PutText( image, "AABBs and contours", text_coord, text_font, text_color )
            elif image_name == "camera":
                image = camera_image
                cv.PutText(image, "No overlay", text_coord, text_font,
                           text_color)
            elif image_name == "difference":
                image = difference
                cv.PutText(image, "Difference Image", text_coord, text_font,
                           text_color)
            elif image_name == "faces":
                # Do face detection
                detect_faces(camera_image, haar_cascade, mem_storage)
                image = camera_image  # Re-use camera image here
                cv.PutText(image, "Face Detection", text_coord, text_font,
                           text_color)
            elif image_name == "threshold":
                # Convert the image to color.
                cv.CvtColor(grey_image, display_image, cv.CV_GRAY2RGB)
                image = display_image  # Re-use display image here
                cv.PutText(image, "Motion Mask", text_coord, text_font,
                           text_color)

            cv.ShowImage("Target", image)

            if self.writer:
                cv.WriteFrame(self.writer, image)

            frame_t1 = time.time()

        t1 = time.time()
        time_delta = t1 - t0
        processed_fps = float(frame_count) / time_delta
        print "Got %d frames. %.1f s. %f fps." % (frame_count, time_delta,
                                                  processed_fps)
示例#18
0
 def approx_poly(self):
     self.contours = cv.ApproxPoly(self.contours, self.storage,
                                   cv.CV_POLY_APPROX_DP, 3, 1)
     return self
示例#19
0
文件: first.py 项目: arjun001/project
    def detect_motion(self, sensitivity='medium'):

        #Finding Video Size from the first frame
        frame = cv.QueryFrame(self.video_handle)
        frame_size = cv.GetSize(frame)
        '''Initializing Image Variables(to be used in motion detection) with required types and sizes'''
        # Image containg instantaneous moving rectangles
        color_image = cv.CreateImage(frame_size, 8, 3)
        # Resizing to window size
        color_output = cv.CreateImage(self.window_size, 8, 3)
        # Grey Image used for contour detection
        grey_image = cv.CreateImage(frame_size, cv.IPL_DEPTH_8U, 1)
        # Image storing background (moving pixels are averaged over small time window)
        moving_average = cv.CreateImage(frame_size, cv.IPL_DEPTH_32F, 3)
        # Image for storing tracks resized to window size
        track_output = cv.CreateImage(self.window_size, cv.IPL_DEPTH_8U, 3)
        track_image, track_win = self.init_track_window(frame)

        def totuple(a):
            try:
                return tuple(totuple(i) for i in a)
            except TypeError:
                return a

        first = True
        # Infinite loop for continuous detection of motion
        while True:
            '''########## Pixelwise Detection of Motion in a frame ###########'''
            # Capturing Frame
            color_image = cv.QueryFrame(self.video_handle)

            ##### Sensitivity Control 1 #####
            if (sensitivity == 'medium') or (sensitivity == 'low'):
                # Gaussian Smoothing
                cv.Smooth(color_image, color_image, cv.CV_GAUSSIAN, 3, 0)

            if first:
                difference = cv.CloneImage(color_image)
                temp = cv.CloneImage(color_image)
                cv.ConvertScale(color_image, moving_average, 1.0, 0.0)
                first = False
            else:
                cv.RunningAvg(color_image, moving_average, .020, None)

            # Convert the scale of the moving average.
            cv.ConvertScale(moving_average, temp, 1, 0.0)

            # Minus the current frame from the moving average.
            cv.AbsDiff(color_image, temp, difference)
            #cv.ShowImage("BG",difference)

            # Convert the image to grayscale.
            cv.CvtColor(difference, grey_image, cv.CV_RGB2GRAY)

            ##### Sensitivity Control 2 #####
            sens_thres = 90 if (sensitivity == 'low') or (self.opt
                                                          == 'cam') else 40
            # Convert the image to black and white.
            cv.Threshold(grey_image, grey_image, sens_thres, 255,
                         cv.CV_THRESH_BINARY)
            '''### Blobing moved adjacent pixels, finding closed contours and bounding rectangles ###'''
            ##### Sensitivity Control 3 #####
            if (sensitivity == 'medium') or (sensitivity == 'low'):
                # Dilate and erode to get people blobs
                ker_size = 20 if self.opt == 'file' else 50
                cv.Dilate(grey_image, grey_image, None, ker_size)
                cv.Erode(grey_image, grey_image, None, 3)

            storage = cv.CreateMemStorage(0)
            contour = cv.FindContours(grey_image, storage, cv.CV_RETR_CCOMP,
                                      cv.CV_CHAIN_APPROX_SIMPLE)
            points = []
            while contour:
                bound_rect = cv.BoundingRect(list(contour))
                polygon_points = cv.ApproxPoly(list(contour), storage,
                                               cv.CV_POLY_APPROX_DP)

                pt1 = (bound_rect[0], bound_rect[1])
                pt2 = (bound_rect[0] + bound_rect[2],
                       bound_rect[1] + bound_rect[3])

                if (self.opt == 'file'):
                    points.append(pt1)
                    points.append(pt2)
                elif (bound_rect[0] - bound_rect[2] >
                      20) and (bound_rect[1] - bound_rect[3] > 20):
                    points.append(pt1)
                    points.append(pt2)

                box = cv.MinAreaRect2(polygon_points)
                box2 = cv.BoxPoints(box)
                box3 = np.int0(np.around(box2))
                box4 = totuple(box3)
                box5 = box4 + (box4[0], )

                # Filling the contours in the greyscale image (visual blobs instead of just contours)
                cv.FillPoly(grey_image, [
                    list(polygon_points),
                ], cv.CV_RGB(255, 255, 255), 0, 0)

                # Following line to draw detected contours as well
                #cv.PolyLine( color_image, [ polygon_points, ], 0, cv.CV_RGB(255,0,0), 1, 0, 0 )

                # Drawing Rectangle around the detected contour
                cv.PolyLine(color_image, [list(box5)], 0, (0, 255, 255), 2)

                if len(points):  # (self.opt == 'file') and
                    center1 = (pt1[0] + pt2[0]) / 2
                    center2 = (pt1[1] + pt2[1]) / 2
                    cv.Circle(color_image, (center1, center2), 5,
                              cv.CV_RGB(0, 255, 0), -1)
                    rad = 3 if self.opt == 'file' else 5
                    cv.Circle(track_image, (center1, center2), rad,
                              cv.CV_RGB(255, 128, 0), -1)

                contour = contour.h_next()

            # Uncomment to track centroid of all the moved boxes (only for WebCam)
            '''
            if (self.opt == 'cam') and len(points):
                center_point = reduce(lambda a, b: ((a[0] + b[0]) / 2, (a[1] + b[1]) / 2), points)
                cv.Circle(track_image, center_point, 15, cv.CV_RGB(255, 128, 0), -1)
            '''
            cv.Resize(color_image, color_output, cv.CV_INTER_AREA)
            cv.ShowImage("Original", color_output)

            cv.Resize(track_image, track_output, cv.CV_INTER_AREA)
            cv.ShowImage(track_win, track_output)

            # Listen for ESC key
            c = cv.WaitKey(7) % 0x100
            if (0xFF & c == 27):
                cv.SaveImage('Tracks_img_042_' + sensitivity + '.jpeg',
                             track_output)
                break
示例#20
0
        cv.Ellipse(image, (dx + 27, dy + 100), (20, 35), 0, 0, 360, _white, -1,
                   8, 0)
        cv.Ellipse(image, (dx + 273, dy + 100), (20, 35), 0, 0, 360, _white,
                   -1, 8, 0)

    # create window and display the original picture in it
    cv.NamedWindow("image", 1)
    cv.ShowImage("image", image)

    # create the storage area
    storage = cv.CreateMemStorage(0)

    # find the contours
    contours = cv.FindContours(image, storage, cv.CV_RETR_TREE,
                               cv.CV_CHAIN_APPROX_SIMPLE, (0, 0))

    # comment this out if you do not want approximation
    contours = cv.ApproxPoly(contours, storage, cv.CV_POLY_APPROX_DP, 3, 1)

    # create the window for the contours
    cv.NamedWindow("contours", 1)

    # create the trackbar, to enable the change of the displayed level
    cv.CreateTrackbar("levels+3", "contours", 3, 7, on_trackbar)

    # call one time the callback, so we will have the 1st display done
    on_trackbar(_DEFAULT_LEVEL)

    # wait a key pressed to end
    cv.WaitKey(0)
示例#21
0
def findSquares4(img, storage):
    N = 11
    sz = (img.width & -2, img.height & -2)
    timg = cv.CloneImage(img)
    # make a copy of input image
    gray = cv.CreateImage(sz, 8, 1)
    pyr = cv.CreateImage((sz.width / 2, sz.height / 2), 8, 3)
    # create empty sequence that will contain points -
    # 4 points per square (the square's vertices)
    squares = cv.CreateSeq(0, sizeof_CvSeq, sizeof_CvPoint, storage)
    squares = CvSeq_CvPoint.cast(squares)

    # select the maximum ROI in the image
    # with the width and height divisible by 2
    subimage = cv.GetSubRect(timg, cv.Rect(0, 0, sz.width, sz.height))

    # down-scale and upscale the image to filter out the noise
    cv.PyrDown(subimage, pyr, 7)
    cv.PyrUp(pyr, subimage, 7)
    tgray = cv.CreateImage(sz, 8, 1)
    # find squares in every color plane of the image
    for c in range(3):
        # extract the c-th color plane
        channels = [None, None, None]
        channels[c] = tgray
        cv.Split(subimage, channels[0], channels[1], channels[2], None)
        for l in range(N):
            # hack: use Canny instead of zero threshold level.
            # Canny helps to catch squares with gradient shading
            if (l == 0):
                # apply Canny. Take the upper threshold from slider
                # and set the lower to 0 (which forces edges merging)
                cv.Canny(tgray, gray, 0, thresh, 5)
                # dilate canny output to remove potential
                # holes between edge segments
                cv.Dilate(gray, gray, None, 1)
            else:
                # apply threshold if l!=0:
                #     tgray(x, y) = gray(x, y) < (l+1)*255/N ? 255 : 0
                cv.Threshold(tgray, gray, (l + 1) * 255 / N, 255,
                             cv.CV_THRESH_BINARY)

            # find contours and store them all as a list
            count, contours = cv.FindContours(gray, storage, sizeof_CvContour,
                                              cv.CV_RETR_LIST,
                                              cv.CV_CHAIN_APPROX_SIMPLE,
                                              (0, 0))

            if not contours:
                continue

            # test each contour
            for contour in contours.hrange():
                # approximate contour with accuracy proportional
                # to the contour perimeter
                result = cv.ApproxPoly(contour, sizeof_CvContour, storage,
                                       cv.CV_POLY_APPROX_DP,
                                       cv.ContourPerimeter(contours) * 0.02, 0)
                # square contours should have 4 vertices after approximation
                # relatively large area (to filter out noisy contours)
                # and be convex.
                # Note: absolute value of an area is used because
                # area may be positive or negative - in accordance with the
                # contour orientation
                if (result.total == 4 and abs(cv.ContourArea(result)) > 1000
                        and cv.CheckContourConvexity(result)):
                    s = 0
                    for i in range(5):
                        # find minimum angle between joint
                        # edges (maximum of cosine)
                        if (i >= 2):
                            t = abs(
                                angle(result[i], result[i - 2], result[i - 1]))
                            if s < t:
                                s = t
                    # if cosines of all angles are small
                    # (all angles are ~90 degree) then write quandrange
                    # vertices to resultant sequence
                    if (s < 0.3):
                        for i in range(4):
                            squares.append(result[i])

    return squares