我需要测量这些等离子体细丝,寻找长度和最大厚度

问题描述 投票:0回答:1

我有多张等离子丝的照片,如下所示:

...其中灯丝在图像顶部被屏蔽中断。我需要进行一些图像分析,包括细丝的长度,如果可能的话,还包括它们的最大宽度。对于图像,在灯丝被中断的地方,我需要连接白点并对其进行插值,就像它不会被中断一样。

我尝试使用我找到的代码,但它只接受黑白图像。

# -*- coding: utf-8 -*-
"""
Created on Sat Mar 16 20:44:05 2024

@author: janko
"""

import cv2
import numpy as np
from skimage import morphology, graph
from skan import Skeleton

MAX_JUNCTION = 4    # maximal size of junctions
MAX_ANGLE = 80      # maximal angle in junction
DELTA = 3           # distance from endpoint to inner point to estimate direction at endpoint


def angle(v1, v2):
    rad = np.arctan2(v2[0], v2[1]) - np.arctan2(v1[0], v1[1])
    return np.abs((np.rad2deg(rad) % 360) - 180)


img = cv2.imread('M2ohX.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# dilate and threshold
kernel = np.ones((2, 2), np.uint8)
dilated = cv2.dilate(gray, kernel, iterations=1)
ret, thresh = cv2.threshold(dilated, 245, 255, cv2.THRESH_BINARY)

# skeletonize
skeleton = morphology.skeletonize(thresh, method='lee')
skeleton = morphology.remove_small_objects(skeleton.astype(bool), 100, connectivity=2)

# split skeleton into paths, for each path longer than MAX_JUNCTION get list of point coordinates
g = Skeleton(skeleton)
lengths = np.array(g.path_lengths())
paths = [list(np.array(g.path_coordinates(i)).astype(int)) for i in range(g.n_paths) if lengths[i] > MAX_JUNCTION]

# get endpoints of path and vector to inner point to estimate direction at endpoint
endpoints = [[p[0], np.subtract(p[0], p[DELTA]), i] for i, p in enumerate(paths)] +\
            [[p[-1], np.subtract(p[-1], p[-1 - DELTA]), i] for i, p in enumerate(paths)]

# get each pair of distinct endpoints with the same junction and calculate deviation of angle
angles = []
costs = np.where(skeleton, 1, 255)  # cost array for route_through_array

for i1 in range(len(endpoints)):
    for i2 in range(i1 + 1, len(endpoints)):
        e1, d1, p1 = endpoints[i1]
        e2, d2, p2 = endpoints[i2]
        if p1 != p2:
            p, c = graph.route_through_array(costs, e1, e2)       # check connectivity of endpoints at junction
            if c <= MAX_JUNCTION:
                deg = angle(d1, d2)                               # get deviation of directions at junction
                if deg <= MAX_ANGLE:
                    angles.append((deg, i1, i2, p))

# merge paths, with least deviation of angle first
angles.sort(key=lambda a: a[0])

for deg, i1, i2, p in angles:
    e1, e2 = endpoints[i1], endpoints[i2]
    if e1 and e2:
        p1, p2 = e1[2], e2[2]
        paths[p1] = paths[p1] + paths[p2] + p   # merge path 2 into path 1, add junction from route_through_array
        for i, e in enumerate(endpoints):       # switch path 2 at other endpoint to new merged path 1
            if e and e[2] == p2:
                endpoints[i][2] = p1
        paths[p2], endpoints[i1], endpoints[i2] = [], [], []    # disable merged path and endpoints

# display results
for p in paths:
    if p:
        img1 = img.copy()
        for v in p:
            img1[v[0], v[1]] = [0, 0, 255]
        cv2.imshow(f'fiber', img1)
        cv2.waitKey(0)

cv2.destroyAllWindows()
python image-processing computer-vision
1个回答
0
投票

您可以找到包含非零元素的第一行和最后一行。

raw = cv2.imread("image.jpg")
image = cv2.cvtColor(raw, cv2.COLOR_BGR2GRAY)
image = cv2.normalize(image, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
_, binary_image = cv2.threshold(image, 10, 255, cv2.THRESH_BINARY)

您可以调整阈值参数,或使用其他方法,例如自适应阈值。在这里您可以找到更多信息:OpenCV tresholding

non_zero_pixels = cv2.findNonZero(binary_image)
y_coordinates, x_coordinates = non_zero_pixels[:, 0, 1], non_zero_pixels[:, 0, 0]
y1, y2 = min(y_coordinates), max(y_coordinates)
x1, x2 = min(x_coordinates), max(x_coordinates)

height, width = y2 - y1, x2 - x1
print("Height: ", height, "px.   Width: ", width, "px.")

cv2.rectangle(raw, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.imshow("Image", raw)
cv2.waitKey(0)
cv2.destroyAllWindows()

尚不清楚,当一个火焰分裂成多个火焰时,您需要这些火焰的外轮廓的宽度,还是单个子火焰的宽度。

在后一种情况下,您可以简单地编写一个函数来迭代 y2 和 y1 之间的线,当遇到第一个非零像素时,对后续像素进行计数,直到遇到第一个零,依此类推。那么,准确性将取决于阈值的精度。

© www.soinside.com 2019 - 2024. All rights reserved.