2.产生灰度变换函数T1,使得:
0.3r r < 0.35
s = 0.105 + 2.6333(r-0.35) 0.35 ≤ r ≤ 0.65
1 + 0.3(r-1) r > 0.65
用T1对原图像rice.jpg进行处理,显示处理前、后的图像(r,s为归一化灰度)。
rice.jpg
实验仪器
Python+OpenCV
import cv2
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider #调用Slider滑块控件
def set_chinese(): #使得画图时的标题可以为中文
import matplotlib
print("[INFO] matplotlib版本为: %s" % matplotlib.__version__)
matplotlib.rcParams['font.sans-serif'] = ['FangSong']
matplotlib.rcParams['axes.unicode_minus'] = False
def three_line_trans(x,x1,y1,x2,y2):
if x1==0 or x1==x2 or x2==255:
print("[INFO] x1={},x2{} ->调用此函数必须满足: x1≠x2且x2≠255以及x1≠0")
return None
#【快速算法】
m1 = (x<x1)
m2 = (x>x1)&(x<x2)
m3 = (x>x2)
output = (y1*x/x1)*m1 + (((y2-y1)/(x2-x1))*(x-x1)+y1)*m2 + (((255-y2)/(255-x2))*(x-x2)+y2)*m3
# 3.获取分段线性函数的点集,用于绘制函数图像
x_point = np.arange(0, 256, 1)
cond2 = [True if (i >= x1 and i <= x2) else False for i in x_point] #!!!不能直接写x1<=x_point<=x2,否则报错。暂时不知道为什么不能双向
y_point = (y1 / x1 * x_point) * (x_point < x1) \
+ ((y2 - y1) / (x2 - x1) * (x_point - x1) + y1) * (cond2) \
+ ((255 - y2) / (255 - x2) * (x_point - x2) + y2) * (x_point > x2)
return output, x_point, y_point
def update_trans(val):
# 读入4个滑动条的值
x1, y1 = slider_x1.val, slider_y1.val
x2, y2 = slider_x2.val, slider_y2.val
if x1>=x2:
x1 = x2-1
if y1>=y2:
y1 = y2-1
output, x_point, y_point = three_line_trans(img_original1, x1=x1, y1=y1, x2=x2, y2=y2)
ax3.clear()
ax3.set_title('分段线性函数图像', fontsize=8)
ax3.grid(True, linestyle=':', linewidth=1)
ax3.plot([x1, x2], [y1, y2], 'ro')
ax3.plot(x_point, y_point, 'g')
ax4.clear()
ax4.set_title('变换后的图像', fontsize=8)
ax4.imshow(output, cmap='gray', vmin=0, vmax=255)
ax5.clear()
ax5.set_title('变换后图像直方图', fontsize=8)
ax5.hist(output.flatten(),bins=50, density=True, color='r', edgecolor='k')
ax5.set_xlim(0, 255) # 设置x轴分布范围
ax5.set_ylim(0, 0.15) # 设置y轴分布范围
ax5.grid(True, linestyle=':', linewidth=1)
if __name__ == '__main__':
set_chinese()
img_original = cv2.imread(r'Fig0316(2)(2nd_from_top).tif')
img_original1 = cv2.cvtColor(img_original, cv2.COLOR_BGR2GRAY)
fig = plt.figure()
ax1 = fig.add_subplot(231)
ax2 = fig.add_subplot(232)
ax3 = fig.add_subplot(233)
ax4 = fig.add_subplot(234)
ax5 = fig.add_subplot(235)
ax1.set_title('原始输入图片',fontsize=8)
ax1.imshow(img_original1,cmap='gray',vmin=0,vmax=255) #官方文档:https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.imshow.html#matplotlib.axes.Axes.imshow
ax2.set_title('原始输入图片直方图',fontsize=8)
ax2.hist(img_original1.flatten(), bins=50, density=True, color='r', edgecolor='k') #bin属性控制直方图横条的数量, density为True则显示的是概率密度
ax2.set_xlim(0, 255) # 设置x轴分布范围
ax2.set_ylim(0, 0.15) # 设置y轴分布范围
ax2.grid(True, linestyle=':', linewidth=1)
plt.subplots_adjust(bottom=0.3)
x1 = plt.axes([0.25, 0.2, 0.45, 0.03], facecolor='lightgoldenrodyellow') #控制横轴的left,bottom,width,height位置和大小
slider_x1 = Slider(x1, '参数x1', 0.0, 255.,
valfmt='%.f', valinit=91, valstep=1) #slider的输入x必须是一个Axes
slider_x1.on_changed(update_trans)
y1 = plt.axes([0.25, 0.16, 0.45, 0.03],
facecolor='lightgoldenrodyellow')
slider_y1 = Slider(y1, '参数y1', 0.0, 255.,
valfmt='%.f', valinit=0, valstep=1)
slider_y1.on_changed(update_trans)
x2 = plt.axes([0.25, 0.06, 0.45, 0.03],
facecolor='white')
slider_x2 = Slider(x2, '参数x2', 0.0, 254.,
valfmt='%.f', valinit=138, valstep=1) #valinit表示slider的点的初始位置(即滑块的初始值)
slider_x2.on_changed(update_trans)
y2 = plt.axes([0.25, 0.02, 0.45, 0.03],
facecolor='white')
slider_y2 = Slider(y2, '参数y2', 0.0, 255.,
valfmt='%.f', valinit=255, valstep=1)
slider_y2.on_changed(update_trans)
slider_x1.set_val(91)
slider_y1.set_val(91)
slider_x2.set_val(138)
slider_y2.set_val(138)
#plt.tight_layout()
plt.show()