简单的射线模型代码
写在前面的话
虽然这只是我之前做了一部分,但是没继续做下去的工作,做出来的也挺垃圾,但是代码是我写,思想是我的,使用请征得同意并注明来源
参考来源
“射线模型”来自这篇文献《 3D neuron tip detection in volumetric microscopy images using an adaptive ray-shooting model》,当然,11年的时候就已经有这个模型了,18年的时候又发了一篇,后面这个团队也用这个模型做了很多事情。在这篇文章里,这个模型主要是射出一些点,点又连成线(如下图所示),计算一下这些点线上的信号强度,再设定一些限制条件,比如线之间的角度,总的强度大小啊这些,就能确定一段有多分叉的树枝里面哪里是分叉点,哪里是末端点等等~
大概就是和下面两张图一样,具体的一些东西,感兴趣的朋友可以研读一下论文啥的~
思路原理
利用这样的射线模型,刚好那段时间手上有个图像分割的项目,结合射线爆发算法,就自己搞了个简单射线模型代码,用来分割较为模糊的边缘~
原始数据类似下图,我们要分割出来的是黑圈周围那一团,和背景颜色很接近,和黑圈区别很大。这一团的边缘不是完全闭合的,会有开口,所以区域增长不能用,不然就会像杯底破了洞,水不知道流成什么样~
对于这样的灰度图像来说,边缘处的灰度值还是会有差异的~,那就让射线模型不断向外射点,达到阈值条件时就画出点,结果就和第二张图一样啦,把大部分点连成线,就分割出来了
代码实现
import cv2
import random
import numpy as np
# 读取图片
IMG= cv2.imread(r"")
#这里就不贴批量获取起始点和黑圈短轴长的代码部分了,直接上射线的部分
def shooting(IMG, start_point, r,angle, points_num, points_step,bound_value):
gray_value = []
coordinate_x = []
coordinate_y = []
# 确定射线方向
num_step = 360 / angle
for theta in range(int(num_step)):
part_angle = theta * angle # 每一次的方向角
# 每个方向以一定的距离和数量射出点
for num in range(1, points_num + 1):
length =num* points_step
x = start_point[0] + (length+r) * np.cos(part_angle)
y = start_point[1] + (length+r) * np.sin(part_angle)
if round(y) >= IMG.shape[0] or round(x) >= IMG.shape[1]:#不等于还不行了
break
else:
coordinate_x.append(str(round(x)))
coordinate_y.append(str(round(y)))
points_value = IMG[round(y), round(x)][0] # BGR,HSV,GRAY都是[y,x]
gray_value.append(points_value)
# 每个方向上后一个点减去前一个点得到差值diff
diff_value = int(gray_value[len(gray_value) - 1]) - int(gray_value[len(gray_value) - 2])
if diff_value > bound_value:
cv2.circle(original_image,
(int(coordinate_x[len(coordinate_x) - 1]), int(coordinate_y[len(coordinate_y) - 1])), 0,
(0, 255, 0), 1)
break
# cv2.circle(IMG, (round(x), round(y)), 0, (0, 0, 255), 1)
# print(gray_value)
gray_value.clear()
coordinate_x.clear()
coordinate_y.clear()
#附带一个可以打点看坐标和灰度值的代码
gray = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
def on_EVENT_LBUTTONDOWN(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
xy = "%d,%d" % (x, y)
cv2.circle(original_image, (x, y), 1, (0, 0, 255), thickness=-1)
cv2.putText(original_image, str(gray[y, x]), (x, y), cv2.FONT_HERSHEY_PLAIN,
1.0, (255, 255, 255), thickness=1)
cv2.imshow("image", original_image)
if __name__ == '__main__':
shooting(图, 射线中心坐标, 黑圈短轴长, 角度 , 点数, 同方向上点之间的间隔, 停下的条件)
cv2.namedWindow("image",0)
# cv2.setMouseCallback("image", on_EVENT_LBUTTONDOWN)
cv2.resizeWindow("image", 8000, 8000);
cv2.imshow("image",original_image)
cv2.waitKey()
就这样啦~因为没有继续研究下去,其中还涉及的计算量等一系列问题就不放上去了,希望在记录我这个科研小垃圾成长的同时,也给大家一些帮助。