python 实现统计图像上的椭圆(ellipse) 内的信息
主要的要点是:
0. 得到椭圆的长短轴方向,半径,以及圆心
import numpy as np
def get_ellipse_parameter(ellipse_info):
""" 得到椭圆的参数 """
long_axis_start_pt = np.array([ellipse_info[0], ellipse_info[1]])
long_axis_end_pt = np.array([ellipse_info[2], ellipse_info[3]])
short_axis_start_pt = np.array([ellipse_info[4], ellipse_info[5]])
short_axis_end_pt = np.array([ellipse_info[6], ellipse_info[7]])
long_radius = np.linalg.norm(long_axis_end_pt - long_axis_start_pt) / 2.0
long_axis = (long_axis_end_pt - long_axis_start_pt) / long_radius / 2.0
short_radius = np.linalg.norm(short_axis_end_pt - short_axis_start_pt) / 2.0
short_axis = (short_axis_end_pt - short_axis_start_pt) / short_radius / 2.0
center = (long_axis_end_pt + long_axis_start_pt) / 2.0
return long_radius, long_axis, short_radius, short_axis, center
1. 求 ellipse 的 boundingbox , 减少计算量
def get_ellipse_bounding_box(ellipse_info):
""" 得到 ellipse bounding box """
assert isinstance(ellipse_info, np.ndarray), \
r'ellipse info 输入的参数必须为 numpy 类型'
x_array = np.array([ellipse_info[0], ellipse_info[2], ellipse_info[4], ellipse_info[6]])
y_array = np.array([ellipse_info[1], ellipse_info[3], ellipse_info[5], ellipse_info[7]])
min_x = min(x_array)
max_x = max(x_array)
min_y = min(y_array)
max_y = max(y_array)
return min_x, min_y, max_x, max_y
2. 判断点是否的椭圆中
def is_in_ellipse(pt, long_radius, long_axis, short_radius, short_axis, center):
""" 判断点是否在椭圆内部 """
normalized_pt = pt - center
normalized_pt_x = np.dot(normalized_pt, long_axis)
normalized_pt_y = np.dot(normalized_pt, short_axis)
result = normalized_pt_x ** 2 / long_radius ** 2 + normalized_pt_y ** 2 / short_radius ** 2
if result <= 1.0:
return True
else:
return False
3. 调用上述方法统计计算
def cal_ellipse_statistic_info(im_2d, ellipse_info):
"""
统计椭圆区域内的像素信息
:param im_2d: numpy 类型的图像信息
:param ellipse_info: 椭圆的长段轴坐标 - 图像坐标系下
[long_axis_start_pt, long_axis_end_pt, short_axis_start_pt, short_axis_end_pt]
:return statistic_info: 统计得到的像素信息 [num_of_pixels, min_value, max_value, mean_value]
"""
assert isinstance(im_2d, np.ndarray) and isinstance(ellipse_info, np.ndarray), \
r'输入的参数必须为 numpy 类型'
# num_of_pixels, min_value, max_value, mean_value
result = [None, None, None, None]
min_x, min_y, max_x, max_y = get_ellipse_bounding_box(ellipse_info)
if min_x < 0 or min_y < 0 or max_y >= im_2d.shape[0] or max_x >= im_2d.shape[1]:
return result
long_radius, long_axis, short_radius, short_axis, center = get_ellipse_parameter(ellipse_info)
num_of_pixels = 0
min_value = 2048
max_value = -2048
sum_of_pixel_values = 0
for x in list(range(min_x, max_x)):
for y in list(range(min_y, max_y)):
if is_in_ellipse(np.array([x, y]), long_radius, long_axis, short_radius, short_axis, center):
num_of_pixels += 1
cur_value = im_2d[y, x]
if min_value > cur_value:
min_value = cur_value
if max_value < cur_value:
max_value = cur_value
sum_of_pixel_values += cur_value
if num_of_pixels > 0:
mean_value = sum_of_pixel_values / num_of_pixels
result = [float(num_of_pixels), float(min_value), float(max_value), float(mean_value)]
return result
4. 测试:
if __name__ == '__main__':
import time
im_2d = np.ones((1024, 1024), dtype=np.int16)
im_2d[138, 138] = 255
im_2d[138, 130] = -200
# ellipse_info = np.array([108, 128, 148, 128, 128, 108, 128, 148])
ellipse_info = np.array([312, 512, 712, 512, 512, 312, 512, 712])
begin = time.time()
statistic_result = cal_ellipse_statistic_info(im_2d, ellipse_info)
end = time.time()
print('cost time {} s'.format(end - begin))
print('num_of_pixels - min_value - max_value - mean_value : {}'.format(statistic_result))
5. 最终,时间性能
大约 40 * 40 的椭圆,计算时间大约是 10 ms
全部代码如下:
import numpy as np
def get_ellipse_parameter(ellipse_info):
""" 得到椭圆的参数 """
long_axis_start_pt = np.array([ellipse_info[0], ellipse_info[1]])
long_axis_end_pt = np.array([ellipse_info[2], ellipse_info[3]])
short_axis_start_pt = np.array([ellipse_info[4], ellipse_info[5]])
short_axis_end_pt = np.array([ellipse_info[6], ellipse_info[7]])
long_radius = np.linalg.norm(long_axis_end_pt - long_axis_start_pt) / 2.0
long_axis = (long_axis_end_pt - long_axis_start_pt) / long_radius / 2.0
short_radius = np.linalg.norm(short_axis_end_pt - short_axis_start_pt) / 2.0
short_axis = (short_axis_end_pt - short_axis_start_pt) / short_radius / 2.0
center = (long_axis_end_pt + long_axis_start_pt) / 2.0
return long_radius, long_axis, short_radius, short_axis, center
def is_in_ellipse(pt, long_radius, long_axis, short_radius, short_axis, center):
""" 判断点是否在椭圆内部 """
normalized_pt = pt - center
normalized_pt_x = np.dot(normalized_pt, long_axis)
normalized_pt_y = np.dot(normalized_pt, short_axis)
result = normalized_pt_x ** 2 / long_radius ** 2 + normalized_pt_y ** 2 / short_radius ** 2
if result <= 1.0:
return True
else:
return False
def get_ellipse_bounding_box(ellipse_info):
""" 得到 ellipse bounding box """
assert isinstance(ellipse_info, np.ndarray), \
r'ellipse info 输入的参数必须为 numpy 类型'
x_array = np.array([ellipse_info[0], ellipse_info[2], ellipse_info[4], ellipse_info[6]])
y_array = np.array([ellipse_info[1], ellipse_info[3], ellipse_info[5], ellipse_info[7]])
min_x = min(x_array)
max_x = max(x_array)
min_y = min(y_array)
max_y = max(y_array)
return min_x, min_y, max_x, max_y
def cal_ellipse_statistic_info(im_2d, ellipse_info):
"""
统计椭圆区域内的像素信息
:param im_2d: numpy 类型的图像信息
:param ellipse_info: 椭圆的长段轴坐标 - 图像坐标系下
[long_axis_start_pt, long_axis_end_pt, short_axis_start_pt, short_axis_end_pt]
:return statistic_info: 统计得到的像素信息 [num_of_pixels, min_value, max_value, mean_value]
"""
assert isinstance(im_2d, np.ndarray) and isinstance(ellipse_info, np.ndarray), \
r'输入的参数必须为 numpy 类型'
# num_of_pixels, min_value, max_value, mean_value
result = [None, None, None, None]
min_x, min_y, max_x, max_y = get_ellipse_bounding_box(ellipse_info)
if min_x < 0 or min_y < 0 or max_y >= im_2d.shape[0] or max_x >= im_2d.shape[1]:
return result
long_radius, long_axis, short_radius, short_axis, center = get_ellipse_parameter(ellipse_info)
num_of_pixels = 0
min_value = 2048
max_value = -2048
sum_of_pixel_values = 0
for x in list(range(min_x, max_x)):
for y in list(range(min_y, max_y)):
if is_in_ellipse(np.array([x, y]), long_radius, long_axis, short_radius, short_axis, center):
num_of_pixels += 1
cur_value = im_2d[y, x]
if min_value > cur_value:
min_value = cur_value
if max_value < cur_value:
max_value = cur_value
sum_of_pixel_values += cur_value
if num_of_pixels > 0:
mean_value = sum_of_pixel_values / num_of_pixels
result = [float(num_of_pixels), float(min_value), float(max_value), float(mean_value)]
return result
if __name__ == '__main__':
import time
im_2d = np.ones((1024, 1024), dtype=np.int16)
im_2d[138, 138] = 255
im_2d[138, 130] = -200
# ellipse_info = np.array([108, 128, 148, 128, 128, 108, 128, 148])
ellipse_info = np.array([312, 512, 712, 512, 512, 312, 512, 712])
begin = time.time()
statistic_result = cal_ellipse_statistic_info(im_2d, ellipse_info)
end = time.time()
print('cost time {} s'.format(end - begin))
print('num_of_pixels - min_value - max_value - mean_value : {}'.format(statistic_result))

本文介绍如何使用Python高效地计算图像上指定椭圆区域的像素信息,包括获取椭圆参数、计算bounding box、判断点在椭圆内,并提供了一个具体的应用示例。通过10ms计算时间,展示了在处理40x40椭圆时的性能

637

被折叠的 条评论
为什么被折叠?



