2019-12-07 15:59:47 weixin_43991027 阅读数 17
  • Java经典算法讲解

    在面试中,算法题目是必须的,通过算法能够看出一个程序员的编程思维,考察对复杂问题的设计与分析能力,对问题的严谨性都能够体现出来。一个算法的好坏,直接影响一个方法调用的性能,进而影响软件的整体性能。算法是学习所有编程语言的基础,在Java的学习过程中首先也会选择以算法起步,本次课程重点讲解Java开发中常用的基本算法。

    29961 人正在学习 去看看 张中强

图像处理——大津二值化算法(otsu)

大津二值化算法也称为最大类间方法。详细解释参考https://blog.csdn.net/weixin_43991027/article/details/103184478
python代码:

import cv2
import numpy as np

def BGR2GRAY(img):
    b = img[:, :, 0].copy()
    g = img[:, :, 1].copy()
    r = img[:, :, 2].copy()

    gray = 0.2126*r + 0.7152*g + 0.0722*b
    gray = gray.astype(np.uint8)           # 注意数据类型转换
    return gray

def ostu_binarization(gray):
    max_sigma = 0
    max_t = 0
    for _t in range(1, 255):
        v0 = gray[np.where(gray < _t)]
        m0 = np.mean(v0) if len(v0) > 0 else 0
        w0 = len(v0) / (H*W)
        v1 = gray[np.where(gray >= _t)]
        m1 = np.mean(v1) if len(v1) > 0 else 0
        w1 = len(v1)/ (H*W)
        sigma = w0 * w1 * ((m0-m1) ** 2)
        if sigma > max_sigma:
            max_sigma = sigma
            max_t = _t

    print('th:', max_t)
    th = max_t
    gray[gray < th] = 0
    gray[gray >= th] = 255

    return gray

img = cv2.imread("../imori.jpg")
H, W, C = img.shape
gray = BGR2GRAY(img)
otsu_img = ostu_binarization(gray)


cv2.imshow("result", otsu_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

C++代码:

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

// BGR->GRAY
cv::Mat BRG2GRAY(cv::Mat img) {
	int width = img.cols;
	int height = img.rows;

	cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);

	for (int y = 0; y < height; y++) {
		for (int x = 0; x < width; x++) {
			out.at<uchar>(y, x) = 0.2126 * (float)img.at<cv::Vec3b>(y, x)[2]\
				+ 0.7152 * (float)img.at<cv::Vec3b>(y, x)[1]\
				+ 0.0722 * (float)img.at<cv::Vec3b>(y, x)[0];
		}
	}
	return out;
}

cv::Mat Binarization_Otsu(cv::Mat gray) {
	int width = gray.cols;
	int height = gray.rows;

	// 定义获得otsu阈值需要的参数
	double w0 = 0, w1 = 0;
	double m0 = 0, m1 = 0;
	double max_sb = 0, sb = 0;
	int th = 0;
	int val;

	// 获取阈值
	for (int t = 0; t < 255; t++) {
		w0 = 0;
		w1 = 0;
		m0 = 0;
		m1 = 0;

		for (int y = 0; y < height; y++){
			for (int x = 0; x < width; x++){
				val = (int)(gray.at<uchar>(y, x));

				if (val < t)
				{
					w0++;
					m0 += val;
				}
				else
				{
					w1++;
					m1 += val;
				}
			}
		}
		m0 /= w0;
		m1 /= w1;
		w0 /= (height * width);
		w1 /= (height * width);
		sb = w0 * w1 * pow((m0 - m1), 2);

		if (sb > max_sb) {
			max_sb = sb;
			th = t;
		}
	}

	std::cout << "threshold:" << th << std::endl;

	//准备输出
	cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);

	for (int y = 0; y < height; y++)
	{
		for (int x = 0; x < width; x++)
		{
			if (gray.at<uchar>(y, x) > th) {
				out.at<uchar>(y, x) = 255;
			}
			else
			{
				out.at<uchar>(y, x) = 0;
			}
		}
	}
	return out;
}

int main(int argc, const char* argv[]) {
	cv::Mat img = cv::imread("./imori.jpg", cv::IMREAD_COLOR);
	cv::Mat gray = BRG2GRAY(img);
	cv::Mat out = Binarization_Otsu(gray);
	//cv::imwrite("out.jpg", out);
	cv::imshow("sample", out);
	cv::waitKey(0);
	cv::destroyAllWindows();

	return 0;
}
2011-04-20 10:29:00 cxf7394373 阅读数 21804
  • Java经典算法讲解

    在面试中,算法题目是必须的,通过算法能够看出一个程序员的编程思维,考察对复杂问题的设计与分析能力,对问题的严谨性都能够体现出来。一个算法的好坏,直接影响一个方法调用的性能,进而影响软件的整体性能。算法是学习所有编程语言的基础,在Java的学习过程中首先也会选择以算法起步,本次课程重点讲解Java开发中常用的基本算法。

    29961 人正在学习 去看看 张中强

      回首前尘,尽是可耻的的往事。每当想起这句话,心里惶惶不可终日,兴趣驱动的学习乐在其中,项目驱动的学习不可不为,压力驱动的学习无疾而终。抛去胡乱YY的国际风雨,社稷民生,我们终究要扎扎实实的度过人生的每个阶段!

      2010年的很长时间都在做图像二值化算法方面的工作,看了一些论文,总结了一些算法,总的来说,在这方面的算法特别多,大致可以分成两类,全局阈值二值化和局部阈值二值化。下面链接了比较基础的几种方法:

     在使用这些算法的同时,发挥了一下主观能动性,并由此发了一篇paper[1]。

      图像二值化属于图像处理比较基础的内容,经过几十年的发展已经比较成熟,只能作为图像处理这个方向的入门。如果还想在这个领域出一些成果,可以结合当前比较热的一些技术,比如Wavelete,从滤波的角度进行处理。

    

 

参考:

[1] An Adaptive Binarization Method for Camera based Document Image

[2] Survey over image thresholding techniques and quantitative performance evaluation

2019-10-12 21:28:18 varyshare 阅读数 78
  • Java经典算法讲解

    在面试中,算法题目是必须的,通过算法能够看出一个程序员的编程思维,考察对复杂问题的设计与分析能力,对问题的严谨性都能够体现出来。一个算法的好坏,直接影响一个方法调用的性能,进而影响软件的整体性能。算法是学习所有编程语言的基础,在Java的学习过程中首先也会选择以算法起步,本次课程重点讲解Java开发中常用的基本算法。

    29961 人正在学习 去看看 张中强

本教程代码已开源到github: https://github.com/varyshare/easy_slam_tutorial/tree/master/Otsu’s_Method_algorithm

Otsu’s 二值化(大津算法)

二值化是什么?有什么用?

PDF扫描成电子版,文字识别,车牌识别等等图像处理场合均需要使用“二值化”操作。我们知道图像是一个矩阵组成,矩阵的元素是一个数字,这个数字是当前像素点对应的颜色(即像素值)。而图片的二值化操作就是将所有像素值变成要么是0要么是1.一般二值化怎么做的呢?答:“设置一个数字d,只要像素值大于这个阈值d那就设置为1,小于这个阈值d那就设置为0。当然也可以大于这个阈值设置为0,小于设置为1”。但是这个阈值怎么找到的呢?计算出一个合适的阈值出来这就是 Otsu’s 二值化(大津算法)要做的事情
下面是一幅图片对应的像素值矩阵(图片就是矩阵):
[200,30,4013,40,45]\begin{bmatrix} 200,30,40\\ 13, 40,45 \end{bmatrix}
假设现在我通过Otsu’s 二值化(大津算法)计算出上面那个图片二值化的最优阈值是39.
那么上面那个图片就会被二值化为:
[1,0,10,1,1]\begin{bmatrix} 1,0,1\\ 0, 1,1 \end{bmatrix}
下面我们实验下。

实验1. 造一个数据

做图像处理必备技能就是人工制造一个纯净的图片检验算法正确性

import numpy as np
import cv2
import matplotlib.pyplot as plt

######我们先制造一个200x200的图片用于二值化实验#######
def get_test_img():
    img_mat = np.zeros((200,200),dtype=np.uint8)# 记得设置成整数,不然opencv会将大于1的浮点数全显示成白色
    for row in range(200):
        for col in range(200):
            img_mat[row][col] = col
    return img_mat
img_mat = get_test_img()
plt.imshow(img_mat,cmap='gray')# 显示图片
plt.xlabel("raw img")

如下所示:
在这里插入图片描述

2. 手工设置阈值进行二值化实验

##########我们设置二值化的阈值为100,将像素值小于100设置为0 (黑色)大于100设置为1 (白色)#######
img_mat = get_test_img() # 注意这是实验1中那个函数
img_mat[img_mat<=100]=0
img_mat[img_mat>100]=1
plt.imshow(img_mat,cmap='gray')# 显示图片
plt.xlabel("binary img")

我们将实验1中的图片二值化为下面这张图。
在这里插入图片描述

Otsu’s 二值化(大津算法)是怎么根据一张图片计算出它二值化的最优阈值的?

它就是统计各个像素值的出现的次数,然后遍历各种阈值(总共有256种可能的选择),然后让被划分的那两类的像素值的方差的加权和最小。加权和的权重就是对应类中像素值之和。这个方差就用统计学中的方差计算公式即可。
我总结下Otsu伪代码:

统计各个像素值的出现次数

while(遍历各种阈值的取值(0到255种可能))
{
    1. 根据当前阈值对图像所有出现的像素值进行分类。
    大于阈值的像素值分为一个类A,小于阈值则分为另外一个类B。(到时候你可以让A类中所有像素值为1,B类所有像素值为0。也可以让类A所有像素值为0.这都是可以你自己定,所以我就用A,B代替了。)
    2. 计算类A的所有像素值的方差SA,计算类B中所有像素值的方差SB
    3. 计算类A中所有像素值之和IA,计算类B中所有像素点的像素值的像素值之和IB
    4. 计算当前阈值划分下两个类的像素值方差的加权和S=IA*SA+SB*IB
    5. 像素值方差的加权和S是否是目前遍历到的阈值划分下最小的那一个值?如果是那就保存当前这种取值
}

通过上面操作最终得到最优的阈值d。

while(遍历所有像素点)
{
   像素值大于阈值d赋值为1,
   像素值小于阈值d赋值为0
}

otsu二值化实验

先用cv2中的otsu库函数看看效果

# 调用cv2中的otsu库
img_mat = get_test_img() # 这是实验1中的那个函数
img_mat = img_mat.astype(np.uint8)
threshold,img_mat = cv2.threshold(img_mat,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
print(threshold)
plt.imshow(img_mat,cmap='gray')

在这里插入图片描述
再我们自己造一个轮子Python代码从零实现otsu二值化算法


import numpy as np
# 自己造轮子写otsu二值化算法
img_mat = get_test_img()
img_mat = img_mat.astype(np.uint8)
##############统计各个像素值的出现次数##############
img_mat_vector = img_mat.flatten()
pixel_counter = np.zeros(256)
for pixel_value in img_mat_vector:
    pixel_counter[pixel_value] += 1

############遍历阈值的各种可能的取值############
min_variance = np.inf
best_threshold = 0
pixel_value = np.arange(256)
for threshold in range(256):
    # 1. 根据阈值对各个像素值进行划分
    pixel_value_A = pixel_value[0:threshold]
    pixel_value_B = pixel_value[threshold:]
    # 2. 计算类A的所有像素值的方差SA,计算类B中所有像素值的方差SB
    totalPixelNum_A = np.sum(pixel_counter[pixel_value_A]) 
    totalPixelNum_B = np.sum(pixel_counter[pixel_value_B])
    
    Probability_pixelvalue_A = pixel_counter[pixel_value_A]/totalPixelNum_A
    Probability_pixelvalue_B = pixel_counter[pixel_value_B]/totalPixelNum_B
    
    meanPixelValue_A = np.sum(pixel_value_A  *  Probability_pixelvalue_A)
    meanPixelValue_B = np.sum(pixel_value_B  *  Probability_pixelvalue_B)
    
    varianceA = np.sum(Probability_pixelvalue_A * (pixel_value_A-meanPixelValue_A)**2)
    varianceB = np.sum(Probability_pixelvalue_B * (pixel_value_B-meanPixelValue_B)**2)
    
    current_total_variance = totalPixelNum_A*varianceA + totalPixelNum_B*varianceB
    if current_total_variance<min_variance:
        min_variance = current_total_variance
        best_threshold = threshold
        
print("最优像素值的阈值为",best_threshold)
#######根据获得的阈值对图像各个像素像素点进行二值化######
img_mat[img_mat<best_threshold] = 0
img_mat[img_mat>=best_threshold] = 1
plt.imshow(img_mat,cmap='gray')

最优像素值的阈值为 100
在这里插入图片描述

用实际数据实践

# 手写一个otsu二值化
img = cv2.imread('./eight.png',cv2.IMREAD_GRAYSCALE)
# 图片数据我已放到github了
# https://github.com/varyshare/easy_slam_tutorial/tree/master/Otsu's_Method_algorithm
##############统计各个像素值的出现次数##############
img_vector = img.flatten()
pixel_counter = np.zeros(256)
for pixel_value in img_vector:
    pixel_counter[pixel_value] += 1

############遍历阈值的各种可能的取值############
min_variance = np.inf
best_threshold = 0
pixel_value = np.arange(256)
for threshold in range(256):
    # 1. 根据阈值对各个像素值进行划分
    pixel_value_A = pixel_value[0:threshold]
    pixel_value_B = pixel_value[threshold:]
    # 2. 计算类A的所有像素值的方差SA,计算类B中所有像素值的方差SB
    totalPixelNum_A = np.sum(pixel_counter[pixel_value_A]) 
    totalPixelNum_B = np.sum(pixel_counter[pixel_value_B])
    
    Probability_pixelvalue_A = pixel_counter[pixel_value_A]/totalPixelNum_A
    Probability_pixelvalue_B = pixel_counter[pixel_value_B]/totalPixelNum_B
    
    meanPixelValue_A = np.sum(pixel_value_A  *  Probability_pixelvalue_A)
    meanPixelValue_B = np.sum(pixel_value_B  *  Probability_pixelvalue_B)
    
    varianceA = np.sum(Probability_pixelvalue_A * (pixel_value_A-meanPixelValue_A)**2)
    varianceB = np.sum(Probability_pixelvalue_B * (pixel_value_B-meanPixelValue_B)**2)
    
    current_total_variance = totalPixelNum_A*varianceA + totalPixelNum_B*varianceB
    if current_total_variance<min_variance:
        min_variance = current_total_variance
        best_threshold = threshold
        
print("最优像素值的阈值为",best_threshold)
#######根据获得的阈值对图像各个像素像素点进行二值化######
img[img<best_threshold] = 0
img[img>=best_threshold] = 1
plt.imshow(img,cmap='gray')

实验结果如下所示
在这里插入图片描述

它的原始图片为:
在这里插入图片描述

你的赞和关注是我分享易懂教程的最大动力

今日github项目推荐:
简单易懂的SLAM实践教程Python代码实践

2013-04-09 22:08:19 mlkiller 阅读数 1778
  • Java经典算法讲解

    在面试中,算法题目是必须的,通过算法能够看出一个程序员的编程思维,考察对复杂问题的设计与分析能力,对问题的严谨性都能够体现出来。一个算法的好坏,直接影响一个方法调用的性能,进而影响软件的整体性能。算法是学习所有编程语言的基础,在Java的学习过程中首先也会选择以算法起步,本次课程重点讲解Java开发中常用的基本算法。

    29961 人正在学习 去看看 张中强

本来想写一些关于walsh 算法的,但是现在还没有完全搞懂只好延后了,先写写简单的。

一、二值化的定义

从维基百科拿过来的定义:

二值化图像分割的一种方法。在二值化图象的时候把大于某个临界灰度值的像素灰度设为灰度极大值,把小于这个值的像素灰度设为灰度极小值,从而实现二值化。

根据阈值选取的不同,二值化的算法分为固定阈值自适应阈值。 比较常用的二值化方法则有:双峰法P参数法迭代法OTSU法等。


二、 二值化的算法


这里就简单讲一下固定阈值的算法:
dst(x,y) =  \fork{\texttt{maxValue}}{if $src(x,y) > T(x,y)$}{0}{otherwise}
拿最简单的灰度图来说如果大于给定值,则设置为255,如果小于则设置为0

对于自适应阈值的意思,应该是统计出图像中直方图的分布情况,然后取分布比较多的值当做阈值。

三代码

void binImage(Mat input ,Mat &out, int threshold)
{
		// accept only char type matrices
    CV_Assert(input.depth() != sizeof(uchar));

	out.create(input.cols,input.rows,CV_8UC1);

    int nRows = input.rows;
    int nCols = input.cols;

    if (input.isContinuous() && out.isContinuous())
    {
        nCols *= nRows;
        nRows = 1;
    }

    int i,j;
    uchar* p;
	uchar* q;
    for( i = 0; i < nRows; ++i)
    {
        p = input.ptr<uchar>(i);
		q = out.ptr<uchar>(i);
        for ( j = 0; j < nCols; ++j)
        {
			if( p[j]> threshold)
				q[j] = 255;
			else
				q[j] = 0;
			
        }
    }

}


四 效率和效果
效率上面比原始图片还是要差一点的。


效果上都一致。
原始 本文
2014-07-19 00:40:57 helloUSB2010 阅读数 25625
  • Java经典算法讲解

    在面试中,算法题目是必须的,通过算法能够看出一个程序员的编程思维,考察对复杂问题的设计与分析能力,对问题的严谨性都能够体现出来。一个算法的好坏,直接影响一个方法调用的性能,进而影响软件的整体性能。算法是学习所有编程语言的基础,在Java的学习过程中首先也会选择以算法起步,本次课程重点讲解Java开发中常用的基本算法。

    29961 人正在学习 去看看 张中强

一、RGB

RGB色彩模式使用RGB模型为图像中每一个像素的RGB分量分配一个0~255范围内的强度值。RGB图像只使用三种颜色,R(red)、G(green)、B(blue),就可以使它们按照不同的比例混合,在屏幕上呈现16777216(256 * 256 * 256)种颜色。

在电脑中,RGB的所谓“多少”就是指亮度,并使用整数来表示。通常情况下,RGB各有256级亮度,用数字表示为从0、1、2...直到255。


二、ARGB

一种色彩模式,也就是RGB色彩模式附加上Alpha(透明度)通道,常见于32位位图存储结构
ARGB---Alpha,Red,Green,Blue.


三、灰度化

 在RGB模型中,如果R=G=B时,则彩色表示一种灰度颜色,其中R=G=B的值叫灰度值,因此,灰度图像每个像素只需一个字节存放灰度值(又称强度值、亮度值),灰度范围为0-255。一般有以下四种方法对彩色图像进行灰度化,具体方法参考:http://blog.csdn.net/evsqiezi/article/details/7905436   


四、二值化

一幅图像包括目标物体、背景还有噪声,要想从多值的数字图像中直接提取出目标物体,最常用的方法就是设定一个全局的阈值T,用T将图像的数据分成两部分:大于T的像素群和小于T的像素群。将大于T的像素群的像素值设定为白色(或者黑色),小于T的像素群的像素值设定为黑色(或者白色)。
比如:计算每一个像素的(R+G+B)/3,如果>127,则设置该像素为白色,即R=G=B=255;否则设置为黑色,即R=G=B=0。
C#实现代码如下:
public Bitmap binarization()
        {
            Bitmap bitImage = new Bitmap(pictureBox1.Image);//二值化pictureBox1中的图片
            Color c;
            int height = pictureBox1.Image.Height;
            int width = pictureBox1.Image.Width;
            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    c = bitImage.GetPixel(j,i);
                    int r = c.R;
                    int g = c.G;
                    int b = c.B;
                    if ((r + g + b) / 3 >= 127)
                    {                       
                        bitImage.SetPixel(j, i, Color.FromArgb(255, 255, 255));                  
                    }
                    else
                    {     
                        bitImage.SetPixel(j, i, Color.FromArgb(0,0,0));
                    }
                }
            }
            return bitImage;
        }
运行结果如图:
左边为处理前,右边为二值化后效果。


五、膨胀算法

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

可以用来填补物体中的空洞。

 

3x3的结构元素,扫描图像的每一个像素

用结构元素与其覆盖的二值图像做操作

如果都为0,结果图像的该像素为0。否则为1

结果:使二值图像扩大一圈


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



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




我设计了一个简单的膨胀算法,依次遍历整个图片的像素,分析每一个像素的周围八个像素,只要该像素周围存在黑色的像素,就设置该像素颜色为黑色。下面是使用膨胀算法处理经过二值化后的图像的C#实现代码:

public bool[] getRoundPixel(Bitmap bitmap, int x, int y)//返回(x,y)周围像素的情况,为黑色,则设置为true
        {
            bool[] pixels=new bool[8];
            Color c;
            int num = 0;
            for (int i = -1; i < 2; i++)
            {
                for (int j = -1; j < 2; j++)
                {
                    c = bitmap.GetPixel(x+i,y+j);
                    if (i != 0 || j != 0)
                    {
                        if (255 == c.G)//因为经过了二值化,所以只要检查RGB中一个属性的值
                        {
                            pixels[num] = false;//为白色,设置为false
                            num++;
                        }
                        else if(0==c.G)
                        {
                            pixels[num] = true;//为黑色,设置为true
                            num++;
                        }
                    }
                }
            }
            return pixels;
        }


public Bitmap expend()
        {
            Bitmap bitImage = new Bitmap(pictureBox2.Image);//处理pictureBox2中的图片
            Bitmap bitImage1 = new Bitmap(pictureBox2.Image);
            int height = pictureBox1.Image.Height;
            int width = pictureBox1.Image.Width;
            bool[] pixels;
            for (int i = 1; i < width-1; i++)
            {
                for (int j = 1; j < height-1; j++)
                {
                    
                    if (bitImage.GetPixel(i, j).R != 0)
                    {
                        pixels = getRoundPixel(bitImage, i, j);
                        for (int k = 0; k < pixels.Length; k++)
                        {
                            if (pixels[k] == true)
                            {
                                //set this piexl's color to black
                                bitImage1.SetPixel(i, j, Color.FromArgb(0,0,0));
                                break;
                            }
                        }
                    }
                }
            }
                return bitImage1;

        }


运行结果如图:


六、腐蚀算法


腐蚀是一种消除边界点,使边界向内部收缩的过程。可以用来消除小且无意义的物体。



3x3的结构元素,扫描图像的每一个像素


用结构元素与其覆盖的二值图像做操作


如果都为1,结果图像的该像素为1。否则为0


结果:使二值图像减小一圈

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



下图中X是被处理的对象,B是结构元素。不难知道,对于任意一个在阴影部分的点aBa包含于X,所以XB腐蚀的结果就是那个阴影部分。阴影部分在X的范围之内,且比X小,就象X被剥掉了一层似的,这就是为什么叫腐蚀的原因。


我设计了一个简单的腐蚀算法,一次遍历图像中每一个像素,检查它四周的八个像素,如果有白色的像素,则设置改点为白色。用二值化处理后的图片进行腐蚀算法C#代码如下:


public Bitmap corrode()
        {
            Bitmap bitImage = new Bitmap(pictureBox2.Image);
            Bitmap bitImage1 = new Bitmap(pictureBox2.Image);
            Color c;
            int height = pictureBox1.Image.Height;
            int width = pictureBox1.Image.Width;
            bool[] pixels;
            for (int i = 1; i < width - 1; i++)
            {
                for (int j = 1; j < height - 1; j++)
                {
                    c = bitImage.GetPixel(i, j);
                    if (bitImage.GetPixel(i, j).R == 0)
                    {
                        pixels = getRoundPixel(bitImage, i, j);
                        for (int k = 0; k < pixels.Length; k++)
                        {
                            if (pixels[k] == false)
                            {
                                //set this piexl's color to black
                                bitImage1.SetPixel(i, j, Color.FromArgb(255, 255, 255));
                                break;
                            }
                        }
                    }
                }
            }
            return bitImage1;
        }

处理后图片变成:



七、开运算

先腐蚀后膨胀的过程称为开运算。用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。


八、闭运算

先膨胀后腐蚀的过程称为闭运算。用来填充物体内细小空洞、连接邻近物体、平滑其边界的同时并不明显改变其面积。




图像处理_二值化

阅读数 1644

图像二值化算法

阅读数 687

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