opencv+python -- 开闭操作、顶帽、黑帽、形态学梯度

开操作 (Open) 闭操作(Close)

  • 图像形态学的重要操作之一,基于膨胀与腐蚀操作组合形成的
  • 主要是应用在二值图像分析中,灰度图像亦可
  • 开操作 = 腐蚀 + 膨胀,输入图像 + 结构元素
  • 闭操作 = 膨胀 + 腐蚀,输入图像 + 结构元素

开闭操作作用

  • 去除小的干扰块 - 开操作
  • 填充闭合区域 - 闭操作
  • 水平或者垂直线提取

顶帽 - tophat 黑帽 - blackhat

  • 顶帽原图像与开操作之间得差值图像
  • 黑帽闭操作与原图像得差值图像

形态学梯度 - gradient

  • 基本梯度
    基本梯度是用膨胀后的图像减去腐蚀后的图像得到差值图像,称为梯度图像也是opencv中支持的计算形态学梯度的方法,而此方法得到梯度又被称为基本梯度
  • 内部梯度
    是用原图像减去腐蚀之后的图像得到差值图像,称为图像的内部梯度
  • 外部梯度
    图像膨胀之后再减去原来的图像得到的差值图像,称为图像的外部梯度

开闭操作

import cv2 as cv


def open_demo(image):
    print(image.shape)
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    cv.imshow("binary image", binary)
    # (15, 1)提取水平线, (1, 15)提取垂直线
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    binary = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel)
    cv.imshow("open-result", binary)


def close_demo(image):
    print(image.shape)
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    cv.imshow("binary image", binary)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    binary = cv.morphologyEx(binary, cv.MORPH_CLOSE, kernel)
    cv.imshow("close-result", binary)


src = cv.imread("./data/LinuxLogo.jpg", cv.IMREAD_COLOR)
# src = cv.imread("./data/tmpl.png", cv.IMREAD_COLOR)
cv.namedWindow("lena", cv.WINDOW_AUTOSIZE)
cv.imshow("lena", src)
# close_demo(src)
open_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

运行结果图

开操作.png

开操作去掉了小点

顶帽、黑帽、形态学梯度

import cv2 as cv
import numpy


def hat_demo(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (15, 15))
    top_dst = cv.morphologyEx(gray, cv.MORPH_TOPHAT, kernel)
    black_dst = cv.morphologyEx(gray, cv.MORPH_BLACKHAT, kernel)
    cimage = numpy.array(gray.shape, numpy.uint8)
    cimage = 100
    top_dst = cv.add(top_dst, cimage)
    black_dst = cv.add(black_dst, cimage)
    cv.imshow("top_hat", top_dst)
    cv.imshow("black_hat", black_dst)


def hat_gray_demo(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (15, 15))
    top_dst = cv.morphologyEx(binary, cv.MORPH_TOPHAT, kernel)
    black_dst = cv.morphologyEx(binary, cv.MORPH_BLACKHAT, kernel)
    cv.imshow("binary_top_hat", top_dst)
    cv.imshow("binary_black_hat", black_dst)


def gradient_demo(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
    basic_dst = cv.morphologyEx(binary, cv.MORPH_GRADIENT, kernel)
    cv.imshow("gradient", basic_dst)

    dm = cv.dilate(image, kernel)
    em = cv.erode(image, kernel)

    internal_dst = cv.subtract(image, em)  # internal gradient
    external_dst = cv.subtract(dm, image)  # external gradient

    cv.imshow("internal_gradient", internal_dst)
    cv.imshow("external_gradient", external_dst)


src = cv.imread("./data/bin.png", cv.IMREAD_COLOR)
cv.namedWindow("lena", cv.WINDOW_AUTOSIZE)
cv.imshow("lena", src)
# hat_demo(src)
# hat_gray_demo(src)
gradient_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

运行结果图

顶帽黑帽.png
梯度运算.png

API PS:C / C++操作

morphologyEx()
void morphologyEx(InputArray src, OutputArray dst, int op, InputArray kernel, Point anchor=Point(-1,-1), intiterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() )

第一个参数,输入图像
第二个参数,输出图像
第三个参数,使用的形态学方法即:
MORPH_OPEN – 开运算(Opening operation)
开运算是对图像先腐蚀再膨胀,可以排除小团的物体转换公式为:


image.png

MORPH_CLOSE – 闭运算(Closing operation)
闭运算是对图像先膨胀再腐蚀,可以排除小型黑洞,变换的公式:


image.png

MORPH_GRADIENT -形态学梯度(Morphological gradient)
返回图片为膨胀图与腐蚀图之差,可以保留物体的边缘轮廓,变换公式为:


image.png

MORPH_TOPHAT - “顶帽”(“Top hat”)
返回图像为原图像与开运算结果图之差,变换公式:


image.png

MORPH_BLACKHAT - “黑帽”(“Black hat“)
返回图片为闭运算结果图与原图像之差,变换公式为:


image.png

第四个参数,InputArray类型的kernel,形态学运算的内核。若为NULL时,表示的是使用参考点位于中心3x3的核。如果设置5*5的即:Mat(5, 5, CV_8U)
第五个参数,Point类型的anchor,锚的位置,其有默认值(-1,-1),表示锚位于中心。
第六个参数,int类型的iterations,迭代使用函数的次数,默认值为1。
第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_ CONSTANT。
第八个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容