两行之间的像素强度值

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

我创建了一个算法,可以检测挤压的胶原蛋白肠衣的边缘,并在图像上的这些边缘之间绘制一条中心线。 Casing with a centerline

这是我的代码:

import numpy as np
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')

img = cv2.imread("C:/Users/5.jpg", cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img, (1500, 1200))

#ROI
fromCenter = False
r = cv2.selectROI(img, fromCenter)
imCrop = img[int(r[1]):int(r[1]+r[3]), int(r[0]):int(r[0]+r[2])]

#Operations on an image
_,thresh = cv2.threshold(imCrop,100,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

blur = cv2.GaussianBlur(opening,(7,7),0)

edges = cv2.Canny(blur, 0,20)

#Edges localization, packing coords into a list
indices = np.where(edges != [0])
coordinates = list(zip(indices[1], indices[0]))
num = len(coordinates)

#Separating into top and bot edge
bot_cor = coordinates[:int(num/2)]
top_cor = coordinates[-int(num/2):]

#Converting to arrays, sorting
a, b = np.array(top_cor), np.array(bot_cor)
a, b = a[a[:,0].argsort()], b[b[:,0].argsort()]

#Edges approximation by a 5th degree polynomial
min_a_x, max_a_x = np.min(a[:,0]), np.max(a[:,0])
new_a_x = np.linspace(min_a_x, max_a_x, imCrop.shape[1])
a_coefs = np.polyfit(a[:,0],a[:,1], 5)
new_a_y = np.polyval(a_coefs, new_a_x)

min_b_x, max_b_x = np.min(b[:,0]), np.max(b[:,0])
new_b_x = np.linspace(min_b_x, max_b_x, imCrop.shape[1])
b_coefs = np.polyfit(b[:,0],b[:,1], 5)
new_b_y = np.polyval(b_coefs, new_b_x)

#Defining a centerline
midx = [np.average([new_a_x[i], new_b_x[i]], axis = 0) for i in range(imCrop.shape[1])]
midy = [np.average([new_a_y[i], new_b_y[i]], axis = 0) for i in range(imCrop.shape[1])]

plt.figure(figsize=(16,8))
plt.title('Cross section')
plt.xlabel('Length of the casing', fontsize=18)
plt.ylabel('Width of the casing', fontsize=18)
plt.plot(new_a_x, new_a_y,c='black')
plt.plot(new_b_x, new_b_y,c='black')
plt.plot(midx, midy, '-', c='blue')
plt.show()

#Converting coords type to a list (plotting purposes)
coords = list(zip(midx, midy))
points = list(np.int_(coords))

mask = np.zeros((imCrop.shape[:2]), np.uint8)
mask = edges

#Plotting
for point in points:
    cv2.circle(mask, tuple(point), 1, (255,255,255), -1)

for point in points:
    cv2.circle(imCrop, tuple(point), 1, (255,255,255), -1)  

cv2.imshow('imCrop', imCrop)
cv2.imshow('mask', mask)

cv2.waitKey(0)
cv2.destroyAllWindows()

现在,我想对顶边缘和中心线之间的区域中每个像素的强度求和(对于中心线和底边缘之间的区域也是如此)。

是否有任何方法可以将ROI限制为检测到的边缘之间的区域,并根据计算出的中心线将其分为两个区域?

或者是否有任何方法可以根据像素坐标来访问包含在边缘和中心线之间的像素?

((这是我的第一篇文章,对于所有错误,在此先表示歉意)

python opencv
1个回答
0
投票

我写了一些天真的代码来获取上部和下部的遮罩。我的代码认为源图像将始终像您的图像:水平条纹。

应用Canny之后,我得到了:

enter image description here

然后我遍历图像数组进行一些循环以填充图像中不需要的区域。分别对上部和下部进行此操作,从而创建蒙版。结果是:

enter image description here

然后,您可以使用此蒙版,使用cv.sumElems仅对您感兴趣的元素求和。

import cv2 as cv

#open as grayscale image
src = cv.imread("colagen.png",cv.IMREAD_GRAYSCALE)

# apply canny and find contours
threshold = 100
canny_output = cv.Canny(src, threshold, threshold * 2)

# find mask for upper part
mask1 = canny_output.copy()
x, y = canny_output.shape
area = 0
for j in range(y):
    area = 0
    for i in range(x):
        if area == 0:
            if mask1[i][j] > 0:
                area = 1
                continue
            else: 
                mask1[i][j] = 255
        elif area == 1:
            if mask1[i][j] > 0:
                area = 2
            else: 
                continue
        else:
            mask1[i][j] = 255
mask1 = cv.bitwise_not(mask1)

# find mask for lower part         
mask2 = canny_output.copy()
x, y = canny_output.shape
area = 0
for j in range(y):
    area = 0
    for i in range(x):
        if area == 0:
            if mask2[-i][j] > 0:
                area = 1
                continue
            else: 
                mask2[-i][j] = 255
        elif area == 1:
            if mask2[-i][j] > 0:
                area = 2
            else: 
                continue
        else:
            mask2[-i][j] = 255
mask2 = cv.bitwise_not(mask2)

# apply masks and calculate sum of elements in upper and lower part
sums = [0,0]
(sums[0],_,_,_) = cv.sumElems(cv.bitwise_and(src,mask1))
(sums[1],_,_,_) = cv.sumElems(cv.bitwise_and(src,mask2))

cv.imshow('src',src)
cv.imshow('canny',canny_output)
cv.imshow('mask1',mask1)
cv.imshow('mask2',mask2)
cv.imshow('masked1',cv.bitwise_and(src,mask1))
cv.imshow('masked2',cv.bitwise_and(src,mask2))
cv.waitKey()

替代品...

可能存在一些函数,可填充Canny结果的区域。我尝试过cv.fillPolycv.floodFill,但没有设法使其轻松工作...但是也许其他人可以帮助您...

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