前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图形图像算法中必须要了解的设计模式(1)

图形图像算法中必须要了解的设计模式(1)

作者头像
OpenCV学堂
发布2018-07-26 10:48:57
1.4K0
发布2018-07-26 10:48:57
举报
文章被收录于专栏:贾志刚-OpenCV学堂

图形图像算法中必须要了解的设计模式(1)

随着信息的多元化,信息的概念不仅仅指的是文字,它还包含图片、声音、视频等其它丰富的信息。文字信息越来越多地被图片、声音、视频信息所替代,而视频又是由一针一针的图像组成的,因此图形图像的处理变得越来越热门和重要,众多的专家、学者、工程师投入到这个领域。

作为一个图像算法的研究者,写出一手高级算法当然是令人兴奋的一件事!但你是否有时会有这种感觉:

  1. 写的算法很难通用于所有的数据类型!每来一个新类型的数据,又得改一下算法,或新加一个方法来支持这种类型。
  2. 有时候多个算法需要灵活组合,甚至每个算法的顺序不一样都会产生不一样的效果;每一种组合都要为其构建一个新算法,即累又麻烦。
  3. 算法越来越多,自建的算法库也越来越庞大而难于管理;

这个时候,让你的算法具有更好通用性、拓展性就显得极为重要!因此,你必须要掌握几个重要的设计模式来解决这些问题。今天介绍其中一个最重要的设计模式——装饰模式

装饰模式

装饰模式(Decorator Pattern):动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。

  • 装饰模式可以动态地给一个对象附加更多的功能。
  • 用不同的算法作为装饰器进行多重装饰,可以达到不同算法的灵活组合;装饰的顺序不同,可能产生不同的效果。

应用案例

静态图像其实就是一个二维的像素数组,对图像的处理其实就是对一个二维坐标像素数据的处理。在图像处理中,图像的灰度化、梯度化(锐化)、边缘化、二值化都是图像处理的基本算法,在进行真正的核心算法之前,经常需要进行这些预处理。

如我曾经在开发的一个用于医疗影像领域的细胞检测和识别项目时,就用到这样的一些处理过程:

  1. 将图像规格化(将所有图片缩放到 800*600)
  2. 平滑去噪处理
  3. 图像的灰度化
  4. 图像的梯度化
  5. 图像的二值化
  6. 真正的识别处理,进行ORI区域识别。

这些预处理算法的顺序不同,将对结果产生很大的影响。

下面我们将以图像的边缘提取算法为例演示整个处理过程,为简单起见,假设有两个预处理过程(灰度化、梯度化)和一个核心算法(二值化边缘提取)。有两种处理顺序,分别如下:

  • 灰度化 --> 梯度化 --> 核心算法:边缘提取算法:
  • 梯度化 --> 灰度化 --> 核心算法:边缘提取算法:

如果你来实现,代码会怎么实现呢? ... ... 也许你会说那还不简单!立马就能想到针对两个处理顺序分别写两个方法:

代码语言:javascript
复制
def imageProcessing1():
    print("算法逻辑")
    # todo Something

def imageProcessing2():
    print("算法逻辑")
    # todo Something

那问题来了,如果预处理的过程不止2种,而是有5种;那就会有5! = 120种排列,难道你要写120个方法?想想都可怕!

如果你用装饰模式,那上面这个问题只要两行代码就能搞定:

代码语言:javascript
复制
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)

代码语言:javascript
复制
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)

测试代码如下:

代码语言:javascript
复制
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()

结果如下:

代码语言:javascript
复制
灰度化 --> 梯度化 --> 核心算法:边缘提取算法:
灰度化处理...
梯度化处理...
真正的核心算法:边缘提取算法

梯度化 --> 灰度化 --> 核心算法:边缘提取算法:
梯度化处理...
灰度化处理...
真正的核心算法:边缘提取算法

Get到技能点了吗?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-07-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OpenCV学堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 图形图像算法中必须要了解的设计模式(1)
    • 装饰模式
      • 应用案例
      相关产品与服务
      图像处理
      图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档