コード例 #1
0
    def find_nematode(self, frame):
        gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        ret, gray_frame = cv2.threshold(gray_frame, self.threshold, 255,
                                        cv2.THRESH_BINARY_INV)
        display_frame = frame.copy()
        centers = []
        eccentricities = []
        _, contours, _ = cv2.findContours(gray_frame, cv2.RETR_LIST,
                                          cv2.CHAIN_APPROX_SIMPLE)
        if contours:
            for idx, contour in enumerate(contours):
                if self.min_area * self.ppa < cv2.contourArea(
                        contour) < self.max_area * self.ppa:
                    cv2.drawContours(display_frame, contours, idx, (0, 0, 255),
                                     int(max(1, self.elements_resize_ratio)))
                    m = cv2.moments(contour)
                    cx = int(m['m10'] / m['m00'])
                    cy = int(m['m01'] / m['m00'])
                    cv2.circle(display_frame, (cx, cy), 2, (0, 255, 0), -1)
                    centers.append((cx, cy))
                    ellipse = cv2.fitEllipseDirect(contour)
                    display_frame = cv2.ellipse(display_frame, ellipse,
                                                (0, 255, 0), 2)
                    eccentricities.append(self.get_eccentricity(ellipse))

        return display_frame, centers, eccentricities
def opencv_fitEllipse(img, method="Direct"):
    #assert binary_mask.min() >= 0.0 and binary_mask.max() <= 1.0
    # points = np.argwhere(binary_mask == 1)  # TODO: tune threshold

    contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE,
                                           cv2.CHAIN_APPROX_SIMPLE)

    # c_img = cv2.drawContours(img, contours, -1, (0, 255, 0), 1)
    # plt.figure()
    # plt.imshow(c_img)
    # plt.show()

    for c in contours:
        ellipse = cv2.fitEllipse(c)

    if method == "AMS":
        for c in contours:
            ellipse = cv2.fitEllipseAMS(c)
    elif method == "Direct":
        for c in contours:
            ellipse = cv2.fitEllipseDirect(c)
    elif method == "Simple":
        for c in contours:
            ellipse = cv2.fitEllipse(c)
    else:
        raise ValueError("Wrong method")

    return ellipse
コード例 #3
0
ファイル: ellipse2poly_ttt.py プロジェクト: Trevol/PyQT_Test
def test_distances():
    img_ellipse = np.zeros((300, 300), dtype=np.uint8)

    center, axes, angle = (150.6, 150.34), (100.66, 50.77), 16.58

    cv2.ellipse(img_ellipse,
                intt(center),
                intt(axes),
                angle,
                0,
                360,
                255,
                thickness=2)
    contour = cv2.findContours(img_ellipse, cv2.RETR_EXTERNAL,
                               cv2.CHAIN_APPROX_SIMPLE)[1][0]

    fitted_ellipse = box_to_ellipse(*cv2.fitEllipseDirect(contour))

    contour = utils.normalize_contour(contour)

    poly_cv = cv2.ellipse2Poly(intt(center), intt(axes), round(angle), 0, 360,
                               1)
    print(utils.polygon_polygon_test(poly_cv, contour, -1))
    print(utils.polygon_polygon_test(contour, poly_cv, -1))

    poly_my = utils.ellipseF2Poly_numpy(center, axes, angle, 0, 360, 1)
    poly_my = np.round(poly_my, 0, out=poly_my).astype(np.int32)
    print(utils.polygon_polygon_test(poly_my, contour, -1))
    print(utils.polygon_polygon_test(contour, poly_my, -1))
コード例 #4
0
 def fromContour(cls, contour):
     if contour.len() < 5:
         return None
     center, axes, angle = cv2.fitEllipseDirect(contour.points())
     if math.isnan(axes[0]) or math.isnan(
             axes[1]) or axes[0] == 0 or axes[1] == 0:
         return None
     return cls(center, axes, angle)
コード例 #5
0
def ellipse_fit(points, method="Direct"):
    if method == "AMS":
        (xx, yy), (MA, ma), angle = cv2.fitEllipseAMS(points)
    elif method == "Direct":
        (xx, yy), (MA, ma), angle = cv2.fitEllipseDirect(points)
    elif method == "Simple":
        (xx, yy), (MA, ma), angle = cv2.fitEllipse(points)

    return (xx, yy), (MA, ma), angle
コード例 #6
0
        def __init__(self, points):
            fit_ellipse = cv2.fitEllipseDirect(points)
            self.valid = self.validate_ellipse(fit_ellipse)
            if not self.valid:
                return

            self.center, self.axes, self.angle = utils.box_to_ellipse(
                *fit_ellipse)

            self.axis_a, self.axis_b = self.axes
            self.area = self.axis_a * self.axis_b * np.pi
            self.aspect_ratio = min(self.axes[0], self.axes[1]) / max(
                self.axes[0], self.axes[1])
            self.__poly = self.__min_rect = self.__main_axes_pts = None
コード例 #7
0
def test_EllipseDirect(img):
    imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, binary = cv2.threshold(src=imgray, thresh=180, maxval=255, type=cv2.THRESH_BINARY)

    find = np.where(binary == 255)  # return tuple
    cnt = np.vstack(find).T
    cnt = cnt[:, np.newaxis, :][:, :, ::-1]  # (6000, 1, 2)

    # 并不是把所有点都包裹进去
    ellipse = cv2.fitEllipseDirect(cnt)

    # cvt binary to 3-channels
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            img[i][j] = [binary[i][j], binary[i][j], binary[i][j]]

    cv2.ellipse(img, ellipse, color=(0, 255, 0), thickness=2)
    cv2.imshow('fitEllipseDirect', img)
コード例 #8
0
ファイル: tracker.py プロジェクト: elmadjian/V-Gaze
 def __get_ellipse(self, contour, img):
     '''
     IN: pupil contours and image frame
     OUT: fitted ellipse around pupil and its contours
     '''
     #TODO: if there are multiple contours, return multiple ellipses
     mask = np.zeros(img.shape, np.uint8)
     ellipse = None
     for c in [contour]:
         if len(c) >= 5:
             ellipse = cv2.fitEllipseDirect(c)
             break
     if ellipse is not None:
         mask = cv2.ellipse(mask, ellipse, 255, 2)
         cnt, hiq = cv2.findContours(mask, cv2.RETR_EXTERNAL,
                                     cv2.CHAIN_APPROX_NONE)
         return cnt, ellipse
     return None, None
コード例 #9
0
def compute_ellipticalSF(thresh, cnt):
    # fit minimum bounded rectangle
    rect = cv2.minAreaRect(cnt)
    (rectCoord1, rectCoord2, rotate_angle) = rect

    # fit minimum bounded ellipse
#     ret,thresh = cv2.threshold(img,127,255,0)
    ellipse = cv2.fitEllipseDirect(cnt)  #(x, y), (MA, ma), angle
    ell = cv2.ellipse(thresh,ellipse,(169,169,169),3)
    (ellpCtr_x, ellpCtr_y), (shortAxis, longAxis), angle = ellipse

    # perimeter and area of ellipse
    a = longAxis / 2
    b = shortAxis / 2
    e = np.sqrt(1 - b**2 / a**2)  # eccentricity
    perimt = 4 * a * ellipe(e*e)
    area = np.pi * a * b

    return rectCoord1, rectCoord2, rotate_angle, (ellpCtr_x, ellpCtr_y), shortAxis, longAxis, perimt, area
コード例 #10
0
ファイル: polar.py プロジェクト: elmadjian/PolarGaze
 def update_model(self, centroids):
     '''
     Update the area of pupil displacement
     IN: list of projected pupil centroids
     OUT: ellipse of the area
     '''
     mean = np.mean(centroids, axis=0)
     ellipse_centers = centroids - mean
     polar = self.__to_polar_batch(ellipse_centers)
     extremes = self.__find_extremes(polar, 18)
     cartesian = self.__to_cartesian_batch(extremes) + mean
     self.extremes = cartesian
     cnt = [np.array(cartesian, np.int32)]
     ellipse = cv2.fitEllipseDirect(cnt[0])
     if ellipse is not None:
         self.angle = ellipse[2]
         self.major_axis = ellipse[1][1] / 2
         self.minor_axis = ellipse[1][0] / 2
         self.center = ellipse[0]
         return ellipse
コード例 #11
0
    def filter_good_ellipses(self, contours):
        """
        Filter out all bad ellipses and return the good ones.

        :param contours: The contours in the image
        :return: List of good ellipses
        :rtype: list
        """
        good = []

        for i, c in enumerate(contours):
            if len(c) < 5:  # cant find ellipse with less
                self.logger.warning("Contour is too small: %d", i)
                continue
            ellipse = cv2.fitEllipseDirect(c)
            cv2.ellipse(self.processed, ellipse,
                        (255 - i * (255 / len(contours)), 0, 0), 1)
            if self.check_ellipse(ellipse, c):
                good.append(copy(ellipse))

        return good
コード例 #12
0
def test_fitting_condition(arcs, lines=None):
    arc_points = []
    for arc in arcs:
        for line in arc:
            arc_points.append(line[0])
            arc_points.append(line[1])
    arc_points = np.unique(arc_points, axis=0).astype(np.float64)

    line_points = []
    if lines is not None:
        for line in lines:
            line_points.append(line[0])
            line_points.append(line[1])
    if len(line_points) > 0:
        line_points = np.unique(line_points, axis=0)
        points = np.vstack((arc_points, line_points))
        points = np.unique(points, axis=0)
    else:
        points = arc_points

    if len(points) < 6:
        return True, None

    points = np.array(points).astype(dtype=np.int32)
    ellipse = Ellipse(cv2.fitEllipseDirect(points))

    score_arc = ellipse.fitting_score(arc_points)
    if len(line_points) > 0:
        score_line = ellipse.fitting_score(line_points)
    else:
        score_line = 1.0

    threshold_fit = 0.8

    if score_arc < threshold_fit or score_line < threshold_fit:
        return False, ellipse

    return True, ellipse
コード例 #13
0
def approximate_electrode_outline(img_bw, iterations=20, center=None):
    """
    Iteratively approximate the electrode area in the given binary image.
    :param img_bw: The binary image
    :param iterations: The number of iterations
    :param center: The approximate center of the electrode (if None, center of the image will be assumed)
    :return: an ellipse mask outlining the approximate shape of the electrode,
             the ellipse description ((cx, cy), (ra, rb), angle)
             the outline of the electrodes masked by the returned mask
    """
    # TODO: check if copy is redundant
    img_bw_orig = np.copy(img_bw)
    mask = None
    area = np.nan
    new_area = np.nan
    i = 0
    while not (
            area - new_area
    ) / area < 0.01:  # continue until area change per iteration is less than 1 %
        # get contours
        cont = find_contour(img_bw, center)
        # fit ellipse
        ellipse = cv.fitEllipseDirect(cont)
        # calculate area to determine convergence
        area = new_area
        new_area = ellipse[1][0] * ellipse[1][
            1]  # pseudo area (no need to bother multiplying by pi)
        # update center based on fit
        center = ellipse[0]
        # create ellipse mask to use in next iteration
        mask = get_ellipse_mask(ellipse, img_bw.shape, 25)
        img_bw = cv.bitwise_and(img_bw_orig, mask)
        i += 1
        if i >= iterations:
            break

    return mask
コード例 #14
0
def vrniKroglo(slika, elipsa, izpisujOpozorila=False):
    """
	slika - rabi sliko na kateri isce
	elipsa - kje naj isce
	izpisujOpozorila - ali izpisuje opozorila v cmd
	Vrne tocko kje se nahaja krogla
	"""

    slika = slika.copy()

    if debug: slikaDebug = slika.copy()

    # Maskiram po plosci
    maska = cv.ellipse(np.zeros(slika.shape, dtype=np.uint8), elipsa[0],
                       elipsa[1], elipsa[2], 0, 360, (1, 1, 1), -1)
    slika = np.where(maska == (0, 0, 0), (255, 255, 255),
                     slika).astype(np.uint8)

    # Pretvorim v hsv prostor
    slika = cv.cvtColor(slika, cv.COLOR_BGR2HSV)

    # Maskiram po barvi zogice
    slika = cv.inRange(slika, (0, 0, 0), (180, 60, 110))
    if debug: cv.imshow("krogla maska1", slika)

    # Odstrani majhne tocke
    slika = cv.medianBlur(slika, 3)

    # Zapolni zogo
    kernel = np.ones((3, 3), np.uint8)
    slika = cv.dilate(slika, kernel)
    slika = cv.erode(slika, kernel)

    # Odstrani majhne tocke
    slika = cv.medianBlur(slika, 5)

    if debug: cv.imshow("krogla maska2", slika)

    # Najde obrobe
    obroba = cv.findContours(slika, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)

    # Ce ni nasel obrob
    if obroba is None:
        if izpisujOpozorila: print("Ne najdem robov")
        return None, None

    # Razvrstim obrobe po povrsini
    obrobe = []
    for o in obroba[0]:
        obrobe.append({"o": o, "povrsina": cv.contourArea(o)})
    obrobe = sorted(obrobe, key=lambda o: o["povrsina"], reverse=True)

    for o in obrobe:
        # Povrsina obrobe more vstrezat
        """ Te meje bi lahko določil z razmerjem vrhov.. če so roboti dvignjeni so blizje kameri in zato je zogica vecja """
        if o["povrsina"] < 270 or o["povrsina"] > 970:
            continue

        # Ce imam manj kot 5 tock ne morem dolocit elipse
        if o["o"].shape[0] < 5:
            continue

        # Dolocim elipso na dane tocke obrobe
        tocka, (MA, ma), kot = cv.fitEllipseDirect(o["o"])
        (MA, ma) = (MA / 2, ma / 2)

        if debug: cv.drawContours(slikaDebug, o["o"], -1, (0, 100, 255))
        if debug:
            cv.ellipse(slikaDebug, (int(tocka[0]), int(tocka[1])),
                       (int(MA), int(ma)), int(kot), 0, 360, (255, 255, 255))
        if debug: cv.imshow("krogla slika", slikaDebug)

        # Ali je priblizno krog
        avg = np.average((MA, ma))
        vecji = np.max((MA, ma))
        manjsi = np.max((MA, ma))
        if manjsi / vecji < 0.5:
            continue

        # Ali je primerno velika
        razmerje = np.max(elipsa[1]) / np.max((MA, ma))
        razmerjeRef = 30 / 2.3
        toleranca = 0.2
        if not (razmerje > razmerjeRef *
                (1 - toleranca) and razmerje < razmerjeRef * (1 + toleranca)):
            continue

        # Vrne zaokrozeno
        return (int(tocka[0]), int(tocka[1])), int(avg)

    return None, None
コード例 #15
0
 def assembled_area(parts):
     pts = np.vstack([p.points() for p in parts])
     center, axes, angle = utils.box_to_ellipse(*cv2.fitEllipseDirect(pts))
     return axes[0] * axes[1] * np.pi
コード例 #16
0
 print(len(contours))
 for cnt in contours:
     M = cv2.moments(cnt)
     if M["m00"] != 0:
         cX = int(M["m10"] / M["m00"])
         cY = int(M["m01"] / M["m00"])
     else:
         continue
     area = cv2.contourArea(cnt)
     if area > max_area or area < min_area:
         continue
     x, y, w, h = cv2.boundingRect(cnt)
     rectArea = w * h
     degOfCompactness = float(area) / rectArea
     perimeter = cv2.arcLength(cnt, True)
     (x, y), (MA, ma), angle = cv2.fitEllipseDirect(cnt)
     a = ma / 2
     b = MA / 2
     ratioOfAxis = float(ma) / MA
     ellipseArea = math.pi * a * b
     eccentricity = math.sqrt(pow(a, 2) - pow(b, 2))
     eccentricity = round(eccentricity / a, 2)
     formFactor = pow(perimeter, 2) / 4 * math.pi * area
     roundness = 4 * math.pi * area / pow(perimeter, 2)
     formFactor = round(formFactor, 2)
     roundness = round(roundness, 2)
     areaRatio = float(area) / ellipseArea
     candidates.append((cX, cY, area, perimeter))
     # cv2.ellipse(currFrame,ellipse,(0,255,0),2)
     cv2.drawContours(currFrame, [cnt], -1, (0, 0, 255), 1)
     cv2.putText(currFrame, str(ratioOfAxis), (cX, cY),
コード例 #17
0
def refine_electrode_outline(img_bw, mask):
    # get contour of the ellipse mask
    ell_cont, hierarchy = cv.findContours(mask, cv.RETR_EXTERNAL,
                                          cv.CHAIN_APPROX_NONE)
    ell_cont = ell_cont[0]  # there can be only one contour
    # get centroid of the contour
    m = cv.moments(ell_cont)
    cx = int(m["m10"] / m["m00"])
    cy = int(m["m01"] / m["m00"])
    center = (cx, cy)

    # get apply mask to input image and get contour
    img_bw = cv.bitwise_and(img_bw, mask)
    cont = find_contour(img_bw, center)

    # visualize result
    # img_col = cv.cvtColor(img_bw, cv.COLOR_GRAY2BGR)
    # cv.drawContours(img_col, cont, -1, (255, 0, 0), 3)
    # cv.drawContours(img_col, ell_cont, -1, (0, 255, 0), 3)
    # cv.imshow("Image", img_col)
    # cv.waitKey()

    # check contour against ellipse contour
    contour = np.squeeze(cont)
    exclude_contour = np.squeeze(ell_cont)
    is_on_ellipse = np.zeros((contour.shape[0]), dtype=bool)
    for i1 in range(0, contour.shape[0]):
        if (exclude_contour == contour[i1, :]).all(axis=1).any():
            is_on_ellipse[i1] = True
    is_included = np.logical_not(is_on_ellipse)
    # post-process excluded region (convert to BW image and use morphological operations)
    is_included = np.array(is_included * 255, dtype=np.uint8)  # to bw image
    is_included = np.reshape(is_included, (-1, 1))
    # close small gaps in the contour (random peaks that got excluded)
    strel = cv.getStructuringElement(cv.MORPH_RECT, (1, 51))
    is_included = cv.morphologyEx(is_included, cv.MORPH_CLOSE, strel)
    strel = cv.getStructuringElement(cv.MORPH_RECT, (1, 51))
    is_included = cv.morphologyEx(is_included, cv.MORPH_OPEN, strel)
    # extend excluded regions
    strel = cv.getStructuringElement(cv.MORPH_RECT, (1, 201))
    is_included = cv.morphologyEx(is_included, cv.MORPH_ERODE, strel)
    is_included = is_included > 0
    is_included = np.reshape(is_included, (-1))
    # find islands
    incl_diff = np.diff(np.array(is_included, dtype=np.int8))
    i_start = np.nonzero(incl_diff > 0)[0]
    i_end = np.nonzero(incl_diff < 0)[0]
    # fix length mismatch (in case a transition is at the beginning/end of the data and no caught by diff)
    if len(i_start) < len(i_end):  # fewer starts than ends
        i_start = np.insert(i_start, 0, 0)  # first block starts at index 0
    elif len(i_start) > len(i_end):  # fewer ends than starts
        i_end = np.append(i_end,
                          len(is_included) -
                          1)  # last block ends at last index
    # if lengths still don't match, we have a problem!
    if len(i_start) != len(i_end):
        raise ValueError("can't match start and end of included regions")
    if len(i_start) != 3:
        logger.warning(
            "Expected 3 contour regions to include. Found: {}".format(
                len(i_start)))
    # TODO: solve this problem properly! Not just catch the error
    if i_start[0] > i_end[
            0]:  # start and end don't match -> shift order to match them
        i_end = np.roll(i_end, -1)
    # include_regions = np.concatenate(i_start, i_end, axis=1)  # combine matched start and end indices
    contour_split = []
    for i in range(len(i_start)):
        if i_start[i] < i_end[
                i]:  # the normal case, where start and end are in order
            section = cont[i_start[i] + 1:i_end[i] + 1, :]
        else:
            s1 = cont[i_start[i] + 1:, :]
            s2 = cont[:i_end[i] + 1, :]
            section = np.append(s1, s2, axis=1)

        contour_split.append(np.reshape(section, (-1, 1, 2)))
    # stitch together to get ellipse fit
    cont_stitched = np.concatenate(contour_split)
    ellipse = cv.fitEllipseDirect(cont_stitched)
    return ellipse
コード例 #18
0
    def dea_fit_ellipse(self, img, exclude_mask=None):
        if img is None:
            logger.warning("No binary image specified!")
            return None, None

        # binarize image
        img_bw = get_binary_image(img, closing_radius=10)

        # If no mask is specified, create one with no exclusions
        if exclude_mask is None:
            # If there is no mask, the algorithm is run once with a blank mask to generate a proper mask.
            # We then run fit ellipse normally to generate the actual fit.
            # This step is crucial to ensure that subsequent calls to dea_fit_ellipse return consistent results.
            # The values returned without a mask differ from those with a mask.
            # TODO: maybe fix this mask issue at some point but for now we'll just call fit ellipse twice.
            self.logging.debug(
                "No mask provided for ellipse fitting. Running ellipse fit once to generate mask."
            )
            exclude_mask = np.zeros(img_bw.shape, dtype=np.uint8)
            ellipse, exclude_mask = self.dea_fit_ellipse(img, exclude_mask)

        # get contours
        cont = find_contour(img_bw)
        ellipse = None
        new_area = np.nan
        converged = False
        i = 0
        while not converged:  # continue until area change per iteration is less than 1 %
            # exclude regions of contour
            cont_in = exclude_contour_points(cont, exclude_mask)
            # fit ellipse
            if cont_in is None or len(cont_in) < 5:
                logger.warning(
                    "Unable to fit ellipse because no outline was found.")
                if np.any(exclude_mask > 0):  # if any exclusions were applied
                    exclude_mask = np.zeros(
                        img_bw.shape,
                        dtype=np.uint8)  # reset mask and try again
                    logger.warning("Trying again without any exclusions.")
                    continue
                return None, None  # if we can't fit an ellipse and there was no mask applied, we have to abort

            ellipse = cv.fitEllipseDirect(cont_in)
            # calculate area to determine convergence
            old_area = new_area
            new_area = ellipse[1][0] * ellipse[1][
                1]  # pseudo area (no need to bother multiplying by pi)

            # create ellipse mask and apply inverse to image to create exclude mask
            ellipse_mask = get_ellipse_mask(ellipse, img_bw.shape, 50)
            exclude_mask = cv.bitwise_and(img_bw, cv.bitwise_not(ellipse_mask))

            # dilate exclude mask to overlap ellipse contour
            operation = cv.MORPH_DILATE
            n = 61
            kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (n, n))
            exclude_mask = cv.morphologyEx(exclude_mask, operation, kernel)

            # count iterations to abort after a while if the result does not converge for some reason
            i += 1
            if i >= self.fit_max_iterations:
                break

            if old_area == 0:
                converged = False
            else:
                converged = (old_area - new_area
                             ) / old_area < self.fit_convergence_threshold

        if i < self.fit_max_iterations:
            logger.debug(
                "Electrode outline detection converged after {} iterations".
                format(i))
        else:
            logger.warning(
                "Electrode outline detection did not converge. Aborted after {} iterations"
                .format(i))

        return ellipse, exclude_mask
コード例 #19
0
def add_ellipses_csv():
    """Add ellipses parameters to training_set_pixel_size_and_HC.csv"""
    import numpy as np
    import pandas as pd
    import os
    import cv2
    from PIL import Image
    import matplotlib.pyplot as plt

    df = pd.read_csv("../../data/raw/training_set_pixel_size_and_HC.csv")

    centers_x = list()
    centers_y = list()
    axes_a = list()
    axes_b = list()
    angles = list()

    for i, row in df.iterrows():
        filename = row["filename"]
        print("i: ", i, end="\r")
        img = Image.open(
            os.path.join(
                "../../data/raw/training_set/",
                filename.replace(".png", "_Annotation.png"),
            ))
        img = np.array(img)
        points = np.argwhere(img > 127)
        (xx, yy), (MA, ma), angle = cv2.fitEllipseDirect(points)

        factor = row["pixel size(mm)"]

        center_x_mm = factor * yy
        center_y_mm = factor * xx
        semi_axes_a_mm = factor * ma / 2
        semi_axes_b_mm = factor * MA / 2
        angle_rad = (-angle * np.pi / 180) % np.pi
        # print(center_x_mm, center_y_mm, semi_axes_a_mm, semi_axes_b_mm, angle_rad)

        centers_x.append(center_x_mm)
        centers_y.append(center_y_mm)
        axes_a.append(semi_axes_a_mm)
        axes_b.append(semi_axes_b_mm)
        angles.append(angle_rad)

        h = (semi_axes_a_mm - semi_axes_b_mm)**2 / (semi_axes_a_mm +
                                                    semi_axes_b_mm)**2
        circ = (np.pi * (semi_axes_a_mm + semi_axes_b_mm) *
                (1 + (3 * h) / (10 + np.sqrt(4 - 3 * h))))

        assert np.abs(circ - row["head circumference (mm)"]) < 0.1

        # print("circ: ", circ)
        # print("true circ: ", row["head circumference (mm)"])

        # plt.imshow(img)
        # plt.show()

    df["center_x_mm"] = centers_x
    df["center_y_mm"] = centers_y
    df["semi_axes_a_mm"] = axes_a
    df["semi_axes_b_mm"] = axes_b
    df["angle_rad"] = angles
    print(df)
    df.to_csv(
        "../../data/processed/training_set_pixel_size_and_HC_and_ellipses.csv",
        index=False,
    )
コード例 #20
0
def draw_fitted_ellipse(img, contours, color):
    pts = np.vstack([c.points() for c in contours])
    center, axes, angle = utils.box_to_ellipse(*cv2.fitEllipseDirect(pts))
    cv2.ellipse(img, utils.intt(center), utils.intt(axes), angle, 0, 360,
                color, 1)
コード例 #21
0
def dist_from_fitted_ellipse(contours):
    points = np.vstack([c.points() for c in contours])
    center, exes, angle = utils.box_to_ellipse(*(cv2.fitEllipseDirect(points)))
    ellipse_poly = utils.ellipseF2Poly(center, exes, angle, 0, 360, 1)
    return utils.polygon_polygon_test(points, ellipse_poly, -1)
コード例 #22
0
ファイル: phantomVrhovi.py プロジェクト: DejanBracun/Phantom
def elipsa(tocke, slika, izpisujOpozorila=False):
    """
	Tocke je vektor iz treh tock za elipso
	Vrne parametre elipse
	"""
    slika = slika.copy()

    c = np.average(tocke, axis=0)

    nove = list(tocke)
    for t in tocke:
        nove.append(list(c - np.array(t) + c))
        #cv.drawMarker(slika, tuple(np.array((c - np.array(t) + c), dtype = np.int)), (255, 200, 200), cv.MARKER_TILTED_CROSS, 15)
    (x, y), (MA,
             ma), kot = cv.fitEllipseDirect(np.array(nove).astype(np.int32))
    #MA, ma = int(MA * 1.05), int(ma * 1.05) # Da malo poveča elipso
    #E1, E2, E3 = (int(x), int(y)), (int(MA / 2), int(ma / 2)), int(kot)
    E1, E2, E3 = np.array([x, y]), np.array([MA / 2, ma / 2]), np.array(kot)

    # region Boljše prileganje 2
    hsv = cv.cvtColor(slika, cv.COLOR_BGR2HSV)

    nove = []
    preveriNajvec = 20  # Koliko tock naj najvec preveri predno obupa
    kotZacetni = kotMedVektorji(np.array([1, 0]), tocke[0] - E1)
    kotPremika = 2 * np.pi / preveriNajvec

    # Zmesa seznam (zmesa vrsti red po katerem bo iskal robove)
    vsi = np.arange(preveriNajvec)
    np.random.shuffle(vsi)

    for i in vsi:
        # Kot pod katerem trenutno iscem
        kot = kotPremika * i + kotZacetni
        # Enotski vektor v kateri smeri trenutno iscem
        v = np.array([np.cos(kot), np.sin(kot)])

        # Preveri linijo v katero kaze vektor v
        for s in range(int(np.min(E2) * 0.9), int(np.max(E2) * 1.1), 1):
            # Pixel, ki ga pregleduje
            pix = np.round(v * s + E1).astype(np.uint)

            ## Ce je pixel preblizu tocke vrha odnehaj
            #for t in tocke:
            #	if np.linalg.norm(pix - t) < 10:
            #		break
            #else:

            # Ce je pixel izven meja slike odnehaj
            if pix[0] < 0 or pix[0] > hsv.shape[1] - 1 or pix[1] < 0 or pix[
                    1] > hsv.shape[0] - 1:
                break

            if debug:
                cv.drawMarker(slika, tuple(pix), (0, 100, 50), cv.MARKER_CROSS,
                              1)

            # Preveri ali je pixel dovolj temen
            if hsv[pix[1], pix[0], 2] < 50:
                if debug:
                    cv.drawMarker(slika, tuple(pix), (0, 255, 150),
                                  cv.MARKER_SQUARE, 10)
                nove.append(pix)
                break

        # Ce imam vsaj toliko tock lahko neha z iskanjem
        if len(nove) > 12:
            if debug: cv.imshow("Vrhovi prileganje", slika)
            (x,
             y), (MA,
                  ma), kot = cv.fitEllipseDirect(np.array(nove, dtype=np.int))
            E1, E2, E3 = (int(x), int(y)), (int(MA / 2), int(ma / 2)), int(kot)
            return E1, E2, E3

    if debug: cv.imshow("Vrhovi prileganje", slika)
    if izpisujOpozorila: print("Slabo prileganje")
    return (int(E1[0]), int(E1[1])), (int(E2[0]), int(E2[1])), int(E3)
コード例 #23
0
    imgCp = img.copy()
    (x, y), radius = cv2.minEnclosingCircle(contours[i])
    (x, y, radius) = np.int0((x, y, radius))  # 圆心和半径取整
    cv2.circle(imgCp, (x, y), radius, (0, 0, 255), 2)

    # 拟合椭圆,方法返回的是一个RotatedRectangle,拟合的椭圆即为其内切椭圆
    # 青色
    ellipse = cv2.fitEllipse(contours[i])
    cv2.ellipse(imgCp, ellipse, (255, 255, 0), 2)

    # 拟合椭圆的另外两种方法
    # 蓝色
    ellipse = cv2.fitEllipseAMS(contours[i])
    cv2.ellipse(imgCp, ellipse, (255, 0, 0), 2)
    # 绿色
    ellipse = cv2.fitEllipseDirect(contours[i])
    cv2.ellipse(imgCp, ellipse, (0, 255, 0), 2)
    totImg = cv2.hconcat((totImg, imgCp))

cv2.imshow('Bounding Circle', totImg)


# 考察轮廓的外接多边形
totImg = img.copy()
for i in range(len(contours)):
    # 多边形逼近,得到多边形的角点。使用Douglas-Peucker算法
    imgCp = img.copy()
    # epsilon表示近似多边形周长和源轮廓周长之间的差值,越小则多边形与源轮廓越相似
    e = 0.01 * cv2.arcLength(contours[i], True)  # 取源轮廓周长的百分比作为差值
    approx = cv2.approxPolyDP(contours[i], epsilon=e, closed=True)
    cv2.polylines(imgCp, [approx], True, (0, 255, 0), 2)