随着信息的多元化,信息的概念不仅仅指的是文字,它还包含图片、声音、视频等其它丰富的信息。文字信息越来越多地被图片、声音、视频信息所替代,而视频又是由一针一针的图像组成的,因此图形图像的处理变得越来越热门和重要,众多的专家、学者、工程师投入到这个领域。
作为一个图像算法的研究者,写出一手高级算法当然是令人兴奋的一件事!但你是否有时会有这种感觉:
这个时候,让你的算法具有更好通用性、拓展性就显得极为重要!因此,你必须要掌握几个重要的设计模式来解决这些问题。今天介绍其中一个最重要的设计模式——装饰模式。
装饰模式(Decorator Pattern):动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。
静态图像其实就是一个二维的像素数组,对图像的处理其实就是对一个二维坐标像素数据的处理。在图像处理中,图像的灰度化、梯度化(锐化)、边缘化、二值化都是图像处理的基本算法,在进行真正的核心算法之前,经常需要进行这些预处理。
如我曾经在开发的一个用于医疗影像领域的细胞检测和识别项目时,就用到这样的一些处理过程:
这些预处理算法的顺序不同,将对结果产生很大的影响。
下面我们将以图像的边缘提取算法为例演示整个处理过程,为简单起见,假设有两个预处理过程(灰度化、梯度化)和一个核心算法(二值化边缘提取)。有两种处理顺序,分别如下:
如果你来实现,代码会怎么实现呢? ... ... 也许你会说那还不简单!立马就能想到针对两个处理顺序分别写两个方法:
def imageProcessing1():
print("算法逻辑")
# todo Something
def imageProcessing2():
print("算法逻辑")
# todo Something
那问题来了,如果预处理的过程不止2种,而是有5种;那就会有5! = 120种排列,难道你要写120个方法?想想都可怕!
如果你用装饰模式,那上面这个问题只要两行代码就能搞定:
resultImg1 = GrayProcessor(GradientProcessor(EdgeExtractionProcessor())).processing(img)
resultImg2 = GradientProcessor(GrayProcessor(EdgeExtractionProcessor())).processing(img)
两种处理顺序的图片预览效果如下: 原图
处理顺序1:灰度化 --> 梯度化 --> 核心算法:边缘提取算法
灰度化:
梯度化:
边缘提取
处理顺序2:梯度化 --> 灰度化 --> 核心算法:边缘提取算法
梯度化:
灰度化:
边缘提取:
这里两种不同的预处理顺序,结果是有略微不同的。想知道我是如何将这个代码精简到两行的吗?这都得归功于装饰模式,下面就一起看看装饰模式的实现方式吧!(下面这段代码用OpenCv for Python实现,Python 3.6.3,opencv-3.4.1,numpy-1.14.5)
from abc import ABCMeta, abstractmethod
# 引入ABCMeta和abstractmethod来定义抽象类和抽象方法
class ImageProcessor(metaclass=ABCMeta):
"图像处理的接口类"
@abstractmethod
def processing(self, img):
"图像处理的抽象方法"
pass
class EdgeExtractionProcessor(ImageProcessor):
"边缘提取算法"
def processing(self, img):
super().processing(img)
print("真正的核心算法:边缘提取算法")
newImg = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 5, 10)
return newImg
class ImageDecorator(ImageProcessor):
"图像装饰器"
def __init__(self, processor):
self._decorator = processor
def processing(self, img):
tmpImg = self.preProcessing(img)
return self._decorator.processing(tmpImg)
@abstractmethod
def preProcessing(self, img):
"预处理方法,由子类实现"
pass
class GrayProcessor(ImageDecorator):
"灰度化处理器"
def __init__(self, processor):
super().__init__(processor)
def preProcessing(self, img):
print("灰度化处理...")
return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换了灰度化
class GradientProcessor(ImageDecorator):
"梯度化处理器"
def __init__(self, processor):
super().__init__(processor)
def preProcessing(self, img):
print("梯度化处理...")
x = cv2.Sobel(img, cv2.CV_16S, 1, 0)
y = cv2.Sobel(img, cv2.CV_16S, 0, 1)
absX = cv2.convertScaleAbs(x) # 转回uint8
absY = cv2.convertScaleAbs(y)
return cv2.addWeighted(absX, 0.5, absY, 0.5, 0)
测试代码如下:
def testImageProcessing():
img = cv2.imread("E:\\TestImages\\bird.jpg")
print("灰度化 --> 梯度化 --> 核心算法:边缘提取算法:")
resultImg1 = GrayProcessor(GradientProcessor(EdgeExtractionProcessor())).processing(img)
print()
print("梯度化 --> 灰度化 --> 核心算法:边缘提取算法:")
resultImg2 = GradientProcessor(GrayProcessor(EdgeExtractionProcessor())).processing(img)
print()
cv2.imshow("The result of image process1", resultImg1)
cv2.imshow("The result of image process2", resultImg2)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果如下:
灰度化 --> 梯度化 --> 核心算法:边缘提取算法:
灰度化处理...
梯度化处理...
真正的核心算法:边缘提取算法
梯度化 --> 灰度化 --> 核心算法:边缘提取算法:
梯度化处理...
灰度化处理...
真正的核心算法:边缘提取算法
Get到技能点了吗?
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有