2015-07-24 10:09:57 mao0514 阅读数 2108

概述:

腐蚀是图像形态学的两个基本操作之一,另外一个是膨胀(Dilate)。二值图像上的腐蚀是腐蚀最典

型的运用,但是腐蚀操作同样可以运用于灰度图像。二值图像腐蚀操作最基本的效果是腐蚀图像

中前景色区域的边缘。使得前景图像区域变小,前景图像内部的背景区域被放大。

 

基本原理:

腐蚀操作要求有待处理的2D图像F(x,y)以及操作数矩阵(类似卷积操作中的Kernel矩阵),常见的

为3X3的操作数矩阵。二值图像腐蚀操作的数学定义如下:

1.      假设X是二值图像中所有像素欧几里德坐标的集合,K为3X3的操作数矩阵

2.       Kx表示操作数处理X的结果,x表示起始像素点

3.      腐蚀操作K对X的所有像素点操作,Kx是X所有像素点的子集。

一个二值图像腐蚀的例子如下,操作数矩阵为3X3,起始点为中心像素点,前景像素表示为1,背

景像素表示为0.图示如下:


当操作数在像素矩阵上移动时,任何一个在操作数之下的输入像素为背景像素时,则设置中心像素

为背景像素0,否则中心像素[0,0]下的输入像素值不变。

 

三:程序效果


四:源代码

  1. package com.gloomyfish.morphology;  
  2.   
  3. import java.awt.Color;  
  4. import java.awt.image.BufferedImage;  
  5.   
  6. public class ErosionFilter extends BinaryFilter {  
  7.     private Color backgroundColor;  
  8.       
  9.     public ErosionFilter() {  
  10.         backgroundColor = Color.WHITE;  
  11.     }  
  12.       
  13.     public Color getBackColor() {  
  14.         return backgroundColor;  
  15.     }  
  16.   
  17.     public void setBackColor(Color forgeColor) {  
  18.         this.backgroundColor = forgeColor;  
  19.     }  
  20.       
  21.     @Override  
  22.     public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
  23.         int width = src.getWidth();  
  24.         int height = src.getHeight();  
  25.   
  26.         if ( dest == null )  
  27.             dest = createCompatibleDestImage( src, null );  
  28.   
  29.         int[] inPixels = new int[width*height];  
  30.         int[] outPixels = new int[width*height];  
  31.         src = super.filter(src, null); // we need to create new one  
  32.         getRGB( src, 00, width, height, inPixels );  
  33.         int index = 0, index1 = 0, newRow = 0, newCol = 0;  
  34.         int ta1 = 0, tr1 = 0, tg1 = 0, tb1 = 0;  
  35.         for(int row=0; row<height; row++) {  
  36.             int ta = 0, tr = 0, tg = 0, tb = 0;  
  37.             for(int col=0; col<width; col++) {  
  38.                 index = row * width + col;  
  39.                 ta = (inPixels[index] >> 24) & 0xff;  
  40.                 tr = (inPixels[index] >> 16) & 0xff;  
  41.                 tg = (inPixels[index] >> 8) & 0xff;  
  42.                 tb = inPixels[index] & 0xff;  
  43.                 boolean erosion = false;  
  44.                 for(int offsetY=-1; offsetY<=1; offsetY++) {  
  45.                     for(int offsetX=-1; offsetX<=1; offsetX++) {  
  46.                         if(offsetY==0 && offsetX==0) {  
  47.                             continue;  
  48.                         }  
  49.                         newRow = row + offsetY;  
  50.                         newCol = col + offsetX;  
  51.                         if(newRow <0 || newRow >=height) {  
  52.                             newRow = 0;  
  53.                         }  
  54.                         if(newCol < 0 || newCol >=width) {  
  55.                             newCol = 0;  
  56.                         }  
  57.                         index1 = newRow * width + newCol;  
  58.                         ta1 = (inPixels[index1] >> 24) & 0xff;  
  59.                         tr1 = (inPixels[index1] >> 16) & 0xff;  
  60.                         tg1= (inPixels[index1] >> 8) & 0xff;  
  61.                         tb1 = inPixels[index1] & 0xff;  
  62.                         if(tr1 == backgroundColor.getRed() && tg1 == tb1) {  
  63.                             erosion = true;  
  64.                             break;  
  65.                         }  
  66.                     }  
  67.                     if(erosion){  
  68.                         break;  
  69.                     }  
  70.                 }  
  71.                   
  72.                 if(erosion) {  
  73.                     tr = tg = tb = backgroundColor.getRed();  
  74.                 } else {  
  75.                     tr = tg = tb = 255 - backgroundColor.getRed();  
  76.                 }  
  77.                 outPixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;  
  78.             }  
  79.         }  
  80.         setRGB( dest, 00, width, height, outPixels );  
  81.         return dest;  
  82.     }  
  83.   
  84.   
  85. }  
2016-11-08 23:21:34 attilax 阅读数 1168

Atitit 图像处理—图像形态学(膨胀与腐蚀)

 

1.1. 膨胀与腐蚀1

1.2. 图像处理之二值膨胀及应用2

1.3. 测试原理,可以给一个5*5pic,测试膨胀算法5

1.4. Photoshop里面的处理5

1.5. 类库的处理,好像没找到jhlabs,6

1.6. Attilax 源码6

 

1.1. 膨胀与腐蚀

  说概念可能很难解释,我们来看图,首先是原图:

  膨胀以后会变成这样:

  腐蚀以后则会变成这样:

  看起来可能有些莫名其妙,明明是膨胀,为什么字反而变细了,而明明是腐蚀,为什么字反而变粗了。

实际上,所谓膨胀应该指

  较亮色块膨胀。

而所谓腐蚀应该指

较亮色块腐蚀。

 

1.2. 图像处理之二值膨胀及应用

基本原理:

膨胀是图像形态学的两个基本操作之一,另外一个是腐蚀操作。最典型的应用是在二值图像

中使用这两个基本操作,是很多识别技术中重要的中间处理步骤。在灰度图像中根据阈值同

样可以完成膨胀与腐蚀操作。对一幅二值图像f(x,y)完成膨胀操作,与对图像的卷积操作类

似,要有个操作数矩阵,最常见的为3X3的矩阵,与卷积操作不同的,是如果矩阵中的像素

点有任意一个点的值是前景色,则设置中心像素点为前景色,否则不变。

 

形态学运算中腐蚀,膨胀,开运算和闭运算:
1. 腐蚀是一种消除边界点,使边界向内部收缩的过程。

可以用来消除小且无意义的物体。
腐蚀的算法:
3x3的结构元素,扫描图像的每一个像素
用结构元素与其覆盖的二值图像做操作
如果都为1,结果图像的该像素为1。否则为0
结果:使二值图像减小一圈

2. 膨胀是将与物体接触的所有背景点合并到该物体中,使边界向外部扩张的过程。

可以用来填补物体中的空洞。
膨胀的算法:
3x3的结构元素,扫描图像的每一个像素
用结构元素与其覆盖的二值图像做操作
如果都为0,结果图像的该像素为0。否则为1
结果:使二值图像扩大一圈

3. 先腐蚀后膨胀的过程称为开运算。

用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。

4. 先膨胀后腐蚀的过程称为闭运算。

用来填充物体内细小空洞、连接邻近物体、平滑其边界的同时并不明显改变其面积。

 

 

让我们来看看实际上是怎样进行膨胀运算的。在图6.14中,左边是被处理的图象X(二值图象,我们针对的是黑点),中间是结构元素B。膨胀的方法是,拿B的中心点和X上的点及X周围的点一个一个地对,如果B上有一个点落在X的范围内,则该点就为黑;右边是膨胀后的结果。可以看出,它包括X的所有范围,就象X膨胀了一圈似的。

6.13   膨胀的示意图

6.14   膨胀运算

6.15为图6.11膨胀后的结果图,能够很明显的看出膨胀的效果。

 

 

粉红色的方格每次在X/Y前进一个像素方格,就会产生一个新的输出像素,图中深蓝色的代

表要输出的像素方格,走完全部的像素方格,就得到了所有输出像素。

 

图中,粉红色的矩阵表示卷积操作数矩阵,黑色表示源图像每个方格代表一个像素点。

 

 

 

1.3. 测试原理,可以给一个5*5pic,测试膨胀算法

 */

public class ImgGene4test {

public static void main(String[] args) {

BufferedImage dest = new BufferedImage(5,5 ,1);

imgx.setBackgroudColor_White(dest);

dest.setRGB(2, 2, new Color(0,0,0).getRGB());

imgx.save_overwrite(dest, "C:\\00capch\\p5.jpg");

System.out.println("==f");

 

}

1.4. Photoshop里面的处理

键后有个文字加粗的.不过我想这个应该满足不了你的要求.你可以先把文字栅格化,然后选择->修改->扩展选区,再进行填充.直到你想要的效果.建议你先把文字做得比你想要的大一点.再进行此操作,得到你想要效果后再缩小.因为是把选区进行扩展再填充,所以边边色起据齿,放大做再缩小这个问题就不会严重了.加分加分.

 

选中文字,在“字符”窗口的左下角,点第一个“T”按钮,即可变粗,如果还不够,那就按住ctrl+鼠标单击文字图层=》“选择”=》修改=》扩展,输入扩展数字确定=》新建图层,填充即可

 

1.5. 类库的处理,好像没找到jhlabs,

1.6. Attilax 源码

 

@Override

public BufferedImage filter(BufferedImage src, BufferedImage dest) {

BufferedImage dest2 = imgx.new_BackgroudColor_White(src.getWidth(), src.getHeight());

Matrix mtrx = new Matrix(3, 3).setImg(src);

imgx.trave(src, (x, y) -> {

System.out.println("" + x + ":" + y);

 

mtrx.fill_and_setMtrx_leftTop_XY(x, y);

 

boolean mtrx_hasAnyForgeColor = mtrx.hasAnyForgeColor(mtrx_item_color -> {

// dark,,so is forge color.. bkgrd lit..

return (imgx.isDarkColor(imgx.gray(mtrx_item_color)));

 

});

if (mtrx_hasAnyForgeColor) {

int forgeColor2 = mtrx.getForgeColor();

mtrxCenterXy_inImg = mtrx.getCenterXy();

try {

dest2.setRGB((int) mtrxCenterXy_inImg.get("x"), (int) mtrxCenterXy_inImg.get("y"), forgeColor2);

} catch (ArrayIndexOutOfBoundsException e) {

System.out.println("ArrayIndexOutOfBoundsException  x:" + x + ",y:" + y);

}

 

}

});

 

return dest2;

}

 

 

图像处理之二值膨胀及应用 - 流浪的鱼 - 博客频道 - CSDN.NET.html

图像处理之二值腐蚀 - 流浪的鱼 - 博客频道 - CSDN.NET.html

图像的膨胀与腐蚀、细化 - 公爵女子 - 博客园.html

java,不依赖于第三方jar的图片处理类 - dragonsoar - ITeye技术网站.html

 

作者:: 绰号:老哇的爪子 ( 全名::Attilax Akbar Al Rapanui 阿提拉克斯 阿克巴 阿尔 拉帕努伊 ) 

汉字名:艾提拉(艾龙)   EMAIL:1466519819@qq.com

转载请注明来源: http://blog.csdn.net/attilax

Atiend

 

2014-03-17 21:56:07 chenjiazhou12 阅读数 3455

这次范例相对比较简单,是涉及到形态学操作的问题,原理也是比较简单,学习起来比较轻松,大家看完这次的范例分析就可以明白到底图像的腐蚀和膨胀是怎么回事了。

1、原理

简单来讲,形态学操作就是基于形状的一系列图像处理操作。通过将 结构元素 作用于输入图像来产生输出图像。
最基本的形态学操作有二:腐蚀与膨胀(Erosion 与 Dilation)。 他们的运用广泛:
消除噪声
分割(isolate)独立的图像元素,以及连接(join)相邻的元素。
寻找图像中的明显的极大值区域或极小值区域。
通过以下图像,我们简要来讨论一下膨胀与腐蚀操作,膨胀是取像素值高的点,腐蚀相反,是取像素值低的点。


                      图1、原图

①、膨胀

此操作将图像 A 与任意形状的内核 (B),通常为正方形或圆形,进行卷积。
内核 B 有一个可定义的 锚点, 通常定义为内核中心点。
进行膨胀操作时,将内核 B 划过图像,将内核 B 覆盖区域的最大相素值提取,并代替锚点位置的相素。显然,这一最大化操作将会导致图像中的亮区开始”扩展” (因此有了术语膨胀 dilation )。对上图采用膨胀操作我们得到:

                图2、膨胀图片

与上面原图比较,可以明显的看到图像字母变粗了,膨胀了。

②、腐蚀

腐蚀在形态学操作家族里是膨胀操作的孪生姐妹。它提取的是内核覆盖下的相素最小值。
进行腐蚀操作时,将内核 B 划过图像,将内核 B 覆盖区域的最小相素值提取,并代替锚点位置的相素。
以与膨胀相同的图像作为样本,我们使用腐蚀操作。如下图:


                图3、腐蚀图片

与上面原图比较,可以明显的看到图像字母变细了,腐蚀了。

现在,我们编写一些代码,在窗口中再加上trackbar控件对图像进行操作,这样可以更直观的看到图像的变化。

2、代码实现

#include "stdafx.h"

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>

using namespace cv;

/// 全局变量
Mat src, erosion_dst, dilation_dst;

int erosion_elem = 0;
int erosion_size = 0;
int dilation_elem = 0;
int dilation_size = 0;
int const max_elem = 2;
int const max_kernel_size = 21;

/** Function Headers */
void Erosion( int, void* );
void Dilation( int, void* );

/** @function main */
int main( int argc, char** argv )
{
	/// Load 图像
	src = imread( "LinuxLogo.jpg" );

	if( !src.data )
	{ return -1; }

	/// 创建显示窗口
	namedWindow( "Erosion Demo", CV_WINDOW_AUTOSIZE );
	namedWindow( "Dilation Demo", CV_WINDOW_AUTOSIZE );
	cvMoveWindow( "Dilation Demo", src.cols, 0 );

	/// 创建腐蚀 Trackbar
	createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo",
		&erosion_elem, max_elem,
		Erosion );

	createTrackbar( "Kernel size:\n 2n +1", "Erosion Demo",
		&erosion_size, max_kernel_size,
		Erosion );

	/// 创建膨胀 Trackbar
	createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo",
		&dilation_elem, max_elem,
		Dilation );

	createTrackbar( "Kernel size:\n 2n +1", "Dilation Demo",
		&dilation_size, max_kernel_size,
		Dilation );

	/// Default start
	Erosion( 0, 0 );
	Dilation( 0, 0 );

	waitKey(0);
	return 0;
}

/**  @function Erosion  */
void Erosion( int, void* )
{
	int erosion_type;
	if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; }
	else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; }
	else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }

	Mat element = getStructuringElement( erosion_type,
		Size( 2*erosion_size + 1, 2*erosion_size+1 ),
		Point( erosion_size, erosion_size ) );

	/// 腐蚀操作
	erode( src, erosion_dst, element );
	imshow( "Erosion Demo", erosion_dst );
}

/** @function Dilation */
void Dilation( int, void* )
{
	int dilation_type;
	if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; }
	else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; }
	else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }

	Mat element = getStructuringElement( dilation_type,
		Size( 2*dilation_size + 1, 2*dilation_size+1 ),
		Point( dilation_size, dilation_size ) );
	///膨胀操作
	dilate( src, dilation_dst, element );
	imshow( "Dilation Demo", dilation_dst );
}

3、运行结果


          图4、原图


         图5、膨胀图片


         图6、腐蚀图片

4、用到的类和函数

getStructuringElement:

功能:返回一个指定大小和形态的结构元素

结构:

Mat getStructuringElement(int shape, Size ksize, Point anchor=Point(-1,-1))
shape :核的类型
        MORPH_RECT:矩形,核的定义为:
        E_{ij}=1
      MORPH_ELLIPSE:椭圆
      MORPH_CROSS:交叉型,核的定义为:

      E_{ij} =  \fork{1}{if i=\texttt{anchor.y} or j=\texttt{anchor.x}}{0}{otherwise}
      CV_SHAPE_CUSTOM :自定义类型
ksize :核的大小
anchor : 锚点 位置。不指定锚点位置,则默认锚点在内核中心位置。

dilate:

功能:图像膨胀

结构:

void dilate(InputArray src, OutputArray dst, InputArray element, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() )
src :源图像
dst :目标图像,和源图像有同样的size和type
element :结构元素,可通过getStructuringElement,如果element=Mat(),那么默认核为3*3的矩形结构
anchor: 锚点 位置。不指定锚点位置,则默认锚点在内核中心位置。
iterations :迭代次数
borderType :边缘点插值类型
实现原理:

\texttt{dst} (x,y) =  \max _{(x',y'):  \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')

函数支持(in-place)模式。膨胀可以重复进行 (iterations) 次. 对彩色图像,每个彩色通道单独处理。

erode:

功能:腐蚀图像

结构:

void erode(InputArray src, OutputArray dst, InputArray element, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() )
src :源图像
dst :目标图像,和源图像有同样的size和type
element :结构元素,可通过getStructuringElement,如果element=Mat(),那么默认核为3*3的矩形结构
anchor: 锚点 位置。不指定锚点位置,则默认锚点在内核中心位置。
iterations :迭代次数
borderType :边缘点插值类型
实现原理:

\texttt{dst} (x,y) =  \min _{(x',y'):  \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')

函数支持(in-place)模式。膨胀可以重复进行 (iterations) 次. 对彩色图像,每个彩色通道单独处理。

createTrackbar:

功能:创建trackbar并将它添加到指定的窗口

结构:

int createTrackbar(const string& trackbarname, const string& winname, int* value, int count, TrackbarCallback onChange=0, void* userdata=0)
trackbarname :被创建的trackbar名字
winname :窗口名字,这个窗口将为被创建trackbar的父对象
value :整数指针,它的值将反映滑块的位置。这个变量指定创建时的滑块位置
count :滑块位置的最大值。最小值一直是0
onChange :每次滑块位置被改变的时候,被调用函数的指针。这个函数应该被声明为void Foo(int,void*);第一个参数是trackbar的位置,第二个参数是userdata,如果没有回调函数,这个值可以设为NULL。
userdata :回调函数返回的数据,在没有使用全局变量的时候,可以通过它来处理trackbar事件
补充:

getTrackbarPos:

功能:获取trackbar的位置,也即是value的位置

结构:

 int getTrackbarPos(const string& trackbarname, const string& winname)
trackbarname :trackbar的名字
winname :trackbar父窗口的名字

setTrackbarPos:

功能:设置trackbar位置,也即是value的位置

结构:

void setTrackbarPos(const string& trackbarname, const string& winname, int pos)
trackbarname :trackbar的名字
winname :trackbar父窗口的名字
pos :新的位置

2016-07-05 21:54:45 zhougynui 阅读数 20116

背景知识

结构元素:二维结构元素可以理解成一个二维矩阵,矩阵元素的值为0或者1;通常结构元素要小于待处理的图像。

腐蚀与膨胀基本原理:就是用一个特定的结构元素来与待处理图像按像素做逻辑操作;可以理解成拿一个带孔的网格板(结构元素矩阵中元素为1的为孔)盖住图像的某一部分,然后按照各种不同的观察方式来确定操作类型。

比如:腐蚀操作就是拿这个结构元素的中心位置(假设参与逻辑计算的元素对应与二维矩阵中元素为1的点,即网格板上的孔),在图像上移动时,如果透过所有的孔都能看到底下的图像,那么这个中心点处的图像就保留,否则去除。

腐蚀

       把结构元素B平移a后得到Ba,若Ba包含于X,我们记下这个a点,所有满足上述条件的a点组成的集合称做X被B腐蚀(Erosion)的结果。用公式表示为:E(X)={a| Ba∈X}=XB。原理图如下:


       实际使用时示意图:


      说明:左边是被处理的图象X(二值图象,我们针对的是黑点),中间是结构元素B,那个标有origin的点是中心点,即当前处理元素的位置,我们在介绍模板操作时也有过类似的概念。腐蚀的方法是,拿B的中心点和X上的点一个一个地对比,如果B上的所有点都在X的范围内,则该点保留,否则将该点去掉;右边是腐蚀后的结果。可以看出,它仍在原来X的范围内,且比X包含的点要少,就象X被腐蚀掉了一层。


膨胀

          膨胀(dilation)可以看做是腐蚀的对偶运算,其定义是:把结构元素B平移a后得到Ba,若Ba击中X,我们记下这个a点。所有满足上述条件的a点组成的集合称做XB膨胀的结果。用公式表示为:D(X)={a | BaX}=X  B,如图6.13所示。图6.13X是被处理的对象,B是结构元素,不难知道,对于任意一个在阴影部分的点aBa击中X,所以XB膨胀的结果就是那个阴影部分。阴影部分包括X的所有范围,就象X膨胀了一圈似的,这就是为什么叫膨胀的原因。原理图如下:


实际使用时示意图:



说明:左边是被处理的图象X(二值图象,我们针对的是黑点),中间是结构元素B。膨胀的方法是,拿B的中心点和X上的点及X周围的点一个一个地对,如果B上有一个点落在X的范围内,则该点就为黑;右边是膨胀后的结果。可以看出,它包括X的所有范围,就象X膨胀了一圈似的。


2019-11-19 13:10:19 xiaohe9275 阅读数 9

                                        形态学运算

1、腐蚀与膨胀

腐蚀与膨胀是针对二值化图像而言的。

腐蚀:使用(2k+1)*(2k+1)的模板S对图像A进行腐蚀,当S移动至A中某点z时,如果S能完全包含在A中(设S为所有值都是255的模板,而A的(2k+1)*(2k+1)邻域以及z点值也都是255,那么就说S能完全包含在A中),那么由这样的点z构成的图像即为S对A的腐蚀图像。

膨胀:使用(2k+1)*(2k+1)的模板S'对图像A进行膨胀,当S'移动至A中某点z时,如果S'与A的(2k+1)*(2k+1)邻域以及z点值有重叠,那么由这样的点z构成的图像即为S'对A的膨胀图像。

实现代码:

/*****************************************************************************
函数名		:	ImgErodeDilate
功能		:	腐蚀膨胀
算法实现	:	<可选项>
参数说明	:	tSrcImg 原图像[in]
				ptDstImg 目标图像[out]
				u8TempH 窗体区域高[in]
				u8TempW 窗体区域宽[in]
				u8OpMode 运算模式[in]
返回值说明	:	无
其他说明	:	无
******************************************************************************/
void ImgErodeDilate(MyImage tSrcImg, MyImage *ptDstImg, u8 u8AreaH, u8 u8AreaW, u8 u8OpMode)
{
	/*原图像高、宽、通道数*/
	l32 l32SrcImgHeight = tSrcImg.l32ImgH;
	l32 l32SrcImgWidth = tSrcImg.l32ImgW;

	/*目标图像高、宽(等于原图像)*/
	l32 l32DstImgHeight = l32SrcImgHeight;
	l32 l32DstImgWidth = l32SrcImgWidth;

	MyImageInit(ptDstImg, l32DstImgHeight, l32DstImgWidth, 1);
	for (l32 l32DstImgHeightIdx = 0; l32DstImgHeightIdx < l32DstImgHeight; l32DstImgHeightIdx++)
	{
		for (l32 l32DstImgWidthIdx = 0; l32DstImgWidthIdx < l32DstImgWidth; l32DstImgWidthIdx++)
		{
			u8 u8IsErode = 1;
			u8 u8IsDilate = 0;
			l32 l32DstImgPixelPos = l32DstImgHeightIdx * l32DstImgWidth + l32DstImgWidthIdx; //目标图像像素在内存中的位置
			for (u8 u8MatHeightIdx = 0; u8MatHeightIdx < u8AreaH; u8MatHeightIdx++)
			{
				for (u8 u8MatWidthIdx = 0; u8MatWidthIdx < u8AreaW; u8MatWidthIdx++)
				{
					l32 l32SrcImgHeightIdx = l32DstImgHeightIdx + u8MatHeightIdx - u8(u8AreaH / 2);
					l32 l32SrcImgWidthIdx = l32DstImgWidthIdx + u8MatWidthIdx - u8(u8AreaW / 2);
					l32 l32SrcImgPixelPos = l32SrcImgHeightIdx * l32SrcImgWidth + l32SrcImgWidthIdx; //原图像像素在内存中的位置
					
					if (l32SrcImgHeightIdx >= 0 && l32SrcImgHeightIdx < l32SrcImgHeight && l32SrcImgWidthIdx >= 0 && l32SrcImgWidthIdx < l32SrcImgWidth)
					{
						switch (u8OpMode)
						{
							case MORP_ERODE:
								if (tSrcImg.pu8Data[l32SrcImgPixelPos] != 255)
									u8IsErode = 0;
								break;
							case MORP_DILATE:
								if (tSrcImg.pu8Data[l32SrcImgPixelPos] == 255)
									u8IsDilate = 1;
								break;
							default:break;
						}
					}
				}
			}

			switch (u8OpMode)
			{
				case MORP_ERODE:
					if (u8IsErode)
						ptDstImg->pu8Data[l32DstImgPixelPos] = 255;
					break;
				case MORP_DILATE:
					if (u8IsDilate)
						ptDstImg->pu8Data[l32DstImgPixelPos] = 255;
					break;
				default:break;
			}
		}
	}
}

2、开运算与闭运算

开运算是先腐蚀再膨胀,而闭运算是先膨胀再腐蚀。

实现代码:

/*****************************************************************************
函数名		:	ImgOpenClose
功能		:	开闭运算
算法实现	:	<可选项>
参数说明	:	tSrcImg 原图像[in]
				ptDstImg 目标图像[out]
				u8TempH 窗体区域高[in]
				u8TempW 窗体区域宽[in]
				u8OpMode 运算模式[in]
返回值说明	:	无
其他说明	:	无
******************************************************************************/
void ImgOpenClose(MyImage tSrcImg, MyImage *ptDstImg, u8 u8AreaH, u8 u8AreaW, u8 u8OpMode)
{
	MyImage tImgErode, tImgDilate;
	switch (u8OpMode)
	{
		case MORP_OPEN:
			ImgErodeDilate(tSrcImg, &tImgErode, u8AreaH, u8AreaW, MORP_ERODE);
			ImgErodeDilate(tImgErode, ptDstImg, u8AreaH, u8AreaW, MORP_DILATE);
			break;
		case MORP_CLOSE:
			ImgErodeDilate(tSrcImg, &tImgDilate, u8AreaH, u8AreaW, MORP_DILATE);
			ImgErodeDilate(tImgDilate, ptDstImg, u8AreaH, u8AreaW, MORP_ERODE);
		default:break;
	}
}

3、细化

 

图像处理之二值腐蚀

阅读数 19112

没有更多推荐了,返回首页