当前位置:主页 > 软件编程 > Python代码 >

Python OpenCV实现3种滤镜效果实例

时间:2022-11-04 09:53:17 | 栏目:Python代码 | 点击:

前言

本篇文章要使用OpenCV、Numpy 和Math这3个工具包实现一个简单的滤镜编辑器。在这个滤镜编辑器中,包含了3种滤镜效果,它们分别是浮雕滤镜、雕刻滤镜和凸透镜滤镜。本篇文章将对目标图像(如图1所示)进行处理,使得目标图像分别呈现浮雕滤镜(如图2所示)、雕刻滤镜(如图3所示)和凸透镜滤镜(如图4所示)的视觉效果。

浮雕滤镜效果

为了实现浮雕滤镜效果,首先要把实现浮雕滤镜效果的原理搞清楚、弄明白。实现浮雕滤镜效果的原理如下所示:

明确了实现浮雕滤镜效果的原理后,再来学习一下实现浮雕滤镜效果的算法。实现浮雕滤镜效果的算法如下所示:

[[1, 0], [0, -1]]

掌握了实现浮雕滤镜效果的原理和算法后,下面开始编写用于实现浮雕滤镜效果的方法,即fuDiao()方法。fuDiao()方法是一个自定义的、有参且有返回值的方法,fuDiao()方法的语法格式如下所示:

def fuDiao(img):
    ……# 省略方法体中的代码
    return canvas

参数说明:

 img:与目标图像对应的灰度图像。

返回值说明:

canvas:画布,用于呈现浮雕滤镜效果的图像。

那么,fuDiao()方法被省略的代码各自发挥怎样的作用?此外,被省略的代码又是那些呢?

先要明确fuDiao()方法中被省略的代码各自发挥的作用是什么:

因为用于实现浮雕滤镜效果的卷积核算子是一个二维矩阵,所以需要使用Numpy工具包中的array()方法创建这个二维矩阵。关键代码如下所示:

kernel = np.array([[1, 0], [0, -1]])

分别获取灰度图像中像素的行数和列数。关键代码如下所示:

row = img.shape[0]
col = img.shape[1]

根据灰度图像中像素的行数和列数,创建一个等高、等宽的,纯黑色的画布。关键代码如下所示:

canvas = np.zeros([row, col], dtype=np.uint8)

根据横、纵坐标,使用嵌套的for循环得到灰度图像中的每一个像素。关键代码如下所示:

for i in range(row - 1):
for j in range(col - 1):

使用实现浮雕滤镜效果的卷积核算子,对灰度图像中的每一个像素进行卷积处理,并且为经卷积处理后的每一个像素加上一个灰度偏移值128。关键代码如下所示:

new_value = np.sum(img[i:i + 2, j:j + 2] * kernel) + 128

对于经卷积处理且加上一个灰度偏移值后的每一个像素的像素值,如果大于255,那么等于255;如果小于0,那么等于0。关键代码如下所示:

if new_value > 255:
   new_value = 255
   elif new_value < 0:
      new_value = 0
  else:
    pass

把经过比较后的每一个像素的像素值根据坐标赋值给画布对应位置上的像素。关键代码如下所示:

canvas[i, j] = new_value

结合fuDiao()方法中被省略的代码和它们各自发挥的作用,就能够迅速完成fuDiao()方法的编写。fuDiao()方法的代码如下所示:

def fuDiao(img):
      kernel = np.array([[1, 0], [0, -1]])
      row = img.shape[0]
      col = img.shape[1]
      canvas = np.zeros([row, col], dtype=np.uint8)
      for i in range(row - 1):
         for j in range(col - 1):
             new_value = np.sum(img[i:i + 2, j:j + 2] * kernel) + 128
             if new_value > 255:
                 new_value = 255
              elif new_value < 0:
                 new_value = 0
              else:
                  pass
             canvas[i, j] = new_value
      return canvas

雕刻滤镜效果

实现雕刻滤镜效果的原理与实现浮雕滤镜效果的原理大致相同,实现雕刻滤镜效果的原理如下所示:

虽然实现雕刻滤镜效果的原理与实现浮雕滤镜效果的原理大致相同,但是实现雕刻滤镜效果的算法与实现浮雕滤镜效果的算法大不相同。实现雕刻滤镜效果的算法如下所示:

[[-1, 0],
[0, 1]]

掌握了实现雕刻滤镜效果的原理和算法后,下面开始编写用于实现雕刻滤镜效果的方法,即diaoKe()方法。与fuDiao()方法相同,diaoKe()方法也是一个自定义的、有参且有返回值的方法,diaoKe()方法的语法格式如下所示:

def diaoKe(img):
   ……# 省略方法体中的代码
    return canvas

参数说明:

img:与目标图像对应的灰度图像。

返回值说明:

canvas:画布,用于呈现雕刻滤镜效果的图像。

diaoKe()方法被省略的代码与fuDiao()方法被省略的代码大同小异,首先明确下diaoKe()方法中被省略的代码各自发挥的作用是什么:

用于实现雕刻滤镜效果的卷积核算子与用于实现浮雕滤镜效果的卷积核算子虽然不同,但也是一个二维矩阵,因此需要使用Numpy工具包中的array()方法创建这个二维矩阵。关键代码如下所示:

kernel = np.array([[-1, 0], [0, 1]])

分别获取灰度图像中像素的行数和列数。关键代码如下所示:

row = img.shape[0]
col = img.shape[1]

根据灰度图像中像素的行数和列数,创建一个等高、等宽的,纯黑色的画布。关键代码如下所示:

canvas = np.zeros([row, col], dtype=np.uint8)

根据横、纵坐标,使用嵌套的for循环得到灰度图像中的每一个像素。关键代码如下所示:

for i in range(row - 1):
for j in range(col - 1):

使用实现雕刻滤镜效果的卷积核算子,对灰度图像中的每一个像素进行卷积处理,并且为经卷积处理后的每一个像素加上一个灰度偏移值128。关键代码如下所示:

new_value = np.sum(img[i:i + 2, j:j + 2] * kernel) + 128

对于经卷积处理且加上一个灰度偏移值后的每一个像素的像素值,如果大于255,那么等于255;如果小于0,那么等于0。关键代码如下所示:

  if new_value > 255:
      new_value = 255
  elif new_value < 0:
      new_value = 0
  else:
      pass

把经过比较后的每一个像素的像素值根据坐标赋值给画布对应位置上的像素。关键代码如下所示:

canvas[i, j] = new_value

结合diaoKe()方法中被省略的代码和它们各自发挥的作用,就能够迅速完成diaoKe()方法的编写。diaoKe()方法的代码如下所示:

  def diaoKe(img):
      kernel = np.array([[-1, 0], [0, 1]])
      row = img.shape[0]
      col = img.shape[1]
      canvas = np.zeros([row, col], dtype=np.uint8)
      for i in range(row - 1):
          for j in range(col - 1):
              new_value = np.sum(img[i:i + 2, j:j + 2] * kernel) + 128
              if new_value > 255:
                  new_value = 255
              elif new_value < 0:
                  new_value = 0
              else:
                  pass
              canvas[i, j] = new_value
      return canvas

凸透镜滤镜效果

所谓凸透镜滤镜效果,相当于用户使用凸透镜观察一幅图像而成的视觉效果。实现凸透镜滤镜效果的原理与实现浮雕滤镜效果的原理和实现雕刻滤镜效果的原理大不相同。下面将着重对实现凸透镜滤镜效果的原理进行讲解:

明确了实现凸透镜滤镜效果的原理后,再来学习一下实现凸透镜滤镜效果的算法。实现凸透镜滤镜效果的算法如下所示:

如果目标图像中的某一个像素与目标图像中心之间的距离的平方不大于凸透镜的半径的平方(两个整数进行比较,保证比较结果的精确度),就使用映射函数对这个像素的横、纵坐标进行映射处理。

掌握了实现凸透镜滤镜效果的原理和算法后,下面开始编写用于实现凸透镜滤镜效果的方法,即tuTouJing()方法。与fuDiao()方法和diaoKe()方法相同,tuTouJing()方法也是一个自定义的、有参且有返回值的方法,tuTouJing()方法的语法格式如下所示:

def tuTouJing(img):
    ……# 省略方法体中的代码
    return canvas

参数说明:

 img:目标图像。

返回值说明:

canvas:画布,用于呈现凸透镜滤镜效果的图像。

先要明确tuTouJing()方法中被省略的代码各自发挥的作用是什么:

分别获取目标图像中像素的行数和列数以及目标图像的通道数。关键代码如下所示:

row = img.shape[0]
col = img.shape[1]
channel = img.shape[2]

根据目标图像中像素的行数和列数以及目标图像的通道数,创建一个等高、等宽、等通道数的,纯黑色的画布。关键代码如下所示:

canvas = np.zeros([row, col, channel], dtype=np.uint8)

根据目标图像中像素的行数和列数,分别获取目标图像中心的横、纵坐标。关键代码如下所示:

center_x = row/2
center_y = col/2

比较目标图像中心的横、纵坐标的大小,把较小的数值作为凸透镜的半径。关键代码如下所示:

radius = min(center_x, center_y)

根据横、纵坐标,使用嵌套的for循环得到目标图像中的每一个像素。关键代码如下所示:

for i in range(row):
for j in range(col):

计算目标图像中的每一个像素与目标图像中心之间的距离的平方和距离。关键代码如下所示:

distance = ((i-center_x) * (i-center_x) + (j-center_y) * (j-center_y))
new_dist = math.sqrt(distance)

把目标图像中的每一个像素的像素值根据坐标赋值给画布对应位置上的像素。关键代码如下所示:

canvas[i,j,:] = img[i, j, :]

如果目标图像中的某一个像素与目标图像中心之间的距离的平方不大于凸透镜的半径的平方,就使用映射函数对这个像素的横、纵坐标进行映射处理。关键代码如下所示:

if distance <= radius**2:
new_i = np.int(np.floor(new_dist * (i-center_x) / radius + center_x))
new_j = np.int(np.floor(new_dist * (j-center_y) / radius + center_y))

把经过映射处理后的每一个像素的像素值根据坐标赋值给画布对应位置上的像素。关键代码如下所示:

canvas[i,j,:] = img[new_i, new_j, :]

结合tuTouJing()方法中被省略的代码和它们各自发挥的作用,就能够迅速完成tuTouJing()方法的编写。tuTouJing()方法的代码如下所示:

  def tuTouJing(img):
      row = img.shape[0]
      col = img.shape[1]
      channel = img.shape[2]
      canvas = np.zeros([row, col, channel], dtype=np.uint8)
      center_x = row/2
      center_y = col/2
      radius = min(center_x, center_y)
      for i in range(row):
          for j in range(col):
              distance = ((i-center_x) * (i-center_x) + (j-center_y) * (j-center_y))
              new_dist = math.sqrt(distance)
              canvas[i,j,:] = img[i, j, :]
              if distance <= radius**2:
                  new_i = np.int(np.floor(new_dist * (i-center_x) / radius + center_x))
                  new_j = np.int(np.floor(new_dist * (j-center_y) / radius + center_y))
                  canvas[i,j,:] = img[new_i, new_j, :]
      return canvas

总结

您可能感兴趣的文章:

相关文章