数字图像处理:实验一

    关于数字图像处理的学习,我们首先要学会matlab这个工具来为我们的计算和处理做好编程的基础。(如果有matlab需求,作者将在另外的文章中来进行介绍安装)

        接下来开始我们的数字图像处理的实验。

实验内容:

        编程要求:选一副图像对其进行以下操作

        1)输出所选图像;

        2)对图像进行“红”、“绿”、“蓝”分层提取,并将三幅分层图显示在一个 窗口里,同时在这三个分层图的顶部附上图像的图名;

        3)获得图像的3D灰度分布图;

        4)分别对“红”、“绿”、“蓝”分层图像的某一行提取该行的灰度值图(一 共3副);并且用该行的“红”色灰度值减去“绿”色灰度值,该行的“红” 色灰度值减去“蓝”色灰度值,该行的“绿”色灰度值减去“蓝”色灰度值(一 共3副);将这6幅图显示一个窗口里,同时在这6个图的各自顶部附上图名;         5)类实地,分别对“红”、“绿”、“蓝”分层图像的某一列提取该列的灰度值图(一共3副);并且用该列的“红”色灰度值减去“绿”色灰度值,该 列的“红”色灰度值减去“蓝”色灰度值,该列的“绿”色灰度值减去“蓝”色 灰度值(一共3副);将这6幅图显示一个窗口里,同时在这6个图的各自顶部附上图名;

        6)对所选图像进行垂直和水平方向的Sobel边缘检测,分别显示检测结果;

        7)计算所选图像的直方图,并显示红、绿、蓝三个通道的直方图对比图;

        8)对所选图像进行高斯平滑处理,显示平滑前后对比图;

        9)对平滑后的图像进行Canny边缘检测,显示检测结果。

在做实验时,我们要去了解一些知识点:

1、什么是灰度?什么是3D灰度分布图?

       答:1、灰度的定义

       灰度,又称灰阶,是使用黑色调表示物体,即用黑色为基准色,通过不同的黑色饱和度来显示图像。灰度图像中的每个像素只有一个采样颜色,这类图像通常显示为从最暗的黑色到最亮的白色的灰度变化。灰度色中不包含任何色相,即不存在红色、黄色这样的颜色,而是纯白、纯黑以及两者中的一系列从黑到白的过渡色。灰度的通常表示方法是百分比,范围从0%(白色)到100%(黑色),也可以表示为0~255的范围,其中0代表黑色,255代表白色,中间的数值代表不同等级的灰色。

        2、3D灰度分布图的定义

       3D灰度分布图则是一种特殊的图像表示方法,它将灰度图像的灰度值分布以三维的形式展现出来。具体来说,3D灰度分布图以灰度图像的灰度值为高度(或深度)信息,将图像的每个像素点映射到一个三维空间中,从而形成一个三维的灰度分布图。这种表示方法能够更直观地展示灰度图像的灰度值分布情况,有助于对图像进行更深入的分析和处理。

2、什么是垂直和水平方向的Sobel边缘检测?

答:Sobel边缘检测是一种经典的图像处理技术,它基于图像灰度梯度的计算来识别边缘区域。这种技术特别适用于检测图像中灰度值发生剧烈变化的地方,即边缘。在Sobel边缘检测中,水平和垂直方向的梯度是通过使用特定的3x3卷积核(也称为Sobel算子模板)来计算的。

   2.1、Sobel算子模板

Sobel算子包含两个主要的卷积核,一个用于检测水平方向的边缘,另一个用于检测垂直方向的边缘。

  1. 水平方向(Gx)

    Sobel水平方向算子的模板如下:

    3*3矩阵 :第一行[-1  0  1  ] 第二行[-2  0  2 ]第三行[-1   0  1]

  2. 这个模板与图像的每个像素进行卷积操作,得到的结果表示该像素在水平方向上的梯度值。

  3. 垂直方向(Gy)

    Sobel垂直方向算子的模板如下:

    3*3矩阵 :第一行[-1  -2  -1 ] 第二行[0  0  0 ]第三行[1  2  1]

    同样地,这个模板与图像的每个像素进行卷积操作,得到的结果表示该像素在垂直方向上的梯度值。

梯度计算与边缘检测

在进行Sobel边缘检测时,通常会对图像的每个像素应用上述两个模板,从而得到水平和垂直方向上的梯度值(Gx和Gy)。然后,可以通过以下步骤进行边缘检测:

  1. 计算梯度幅值:梯度幅值G是梯度向量的模,可以通过公式G = sqrt(Gx² + Gy²)计算得到。这个值表示了图像中每个像素点附近的灰度变化强度。

  2. 设定阈值:为了确定哪些像素点属于边缘,需要设定一个阈值。通常,梯度幅值大于该阈值的像素点会被认为是边缘点。

  3. 边缘标记:将梯度幅值大于阈值的像素点标记为边缘点,通常是通过将这些点的值设置为255(白色),而其他点的值设置为0(黑色),从而得到二值化的边缘图像。

注意事项

  • Sobel边缘检测对噪声较为敏感,因此在处理噪声较多的图像时,可能需要进行预处理(如高斯模糊)来减少噪声的影响。
  • Sobel算子主要适用于检测水平和垂直方向的边缘,对于斜向边缘的检测效果可能较差。如果需要检测斜向边缘,可以考虑使用其他边缘检测算法(如Canny边缘检测)。

3、高斯平滑处理

答:基本原理:

        高斯平滑处理的基本思想是使用一个二维的高斯分布函数与图像进行卷积,从而达到平滑图像、去除细节和噪声的效果。高斯分布函数是一种钟形曲线,它在中心点取得最大值,并随着与中心点距离的增大而逐渐减小。这种特性使得高斯平滑在处理图像时,能够更好地保留图像的边缘信息,同时去除不需要的细节和噪声。

       实现方式:高斯平滑的实现方式主要有两种:一是通过离散化窗口滑窗卷积,二是通过傅里叶变换。在实际应用中,最常用的是第一种方式,因为它简单且易于实现。

  1. 离散化窗口滑窗卷积:
    • 首先定义一个二维高斯核(也称为滤波器),其大小由滤波器尺寸和标准差决定。
    • 然后,将高斯核应用于图像的每个像素点,将该像素点与其周围邻域内的像素点进行加权平均计算。权重是根据高斯核的数值分布确定的,距离中心像素越远的像素点权重越小。
  2. 傅里叶变换:
    • 将图像和高斯核分别进行傅里叶变换,将空间域的问题转换到频率域。
    • 在频率域中进行乘法运算,相当于在空间域中进行卷积。
    • 最后,将结果再进行傅里叶逆变换,得到平滑后的图像。

注意:

  1. 在进行高斯平滑处理时,需要注意选择合适的参数,以平衡平滑效果和图像细节保留之间的关系。(这里的参数指的是sigma,这里是高斯核的标准差,这里的实验标准差值是需要调整的,参考学习的资料我放在文章末尾,大家都可以去多学点东西)
  2. 对于边界上的点,通常需要采用特定的处理方式(如复制周围的点到另一面再进行加权平均运算),以避免边界效应。
  3. 高斯平滑处理虽然可以有效地去除噪声和细节,但也可能导致图像的某些重要特征被模糊掉。因此,在实际应用中需要根据具体需求进行权衡。

        总之,高斯平滑处理的过程中会使的图片变得比较连接,少了那种线条的分割感觉,但是在于图像的降噪和视觉上有帮助,但是需要注意选择合适的参数,以平衡平滑效果和图像细节保留之间的关系。

实验过程:(作者这里喜欢薇尔莉特,所以用了她的图片来展示

 1、输出所选图像

A = imread('1.png'); % 读取名为'1.png'的图像文件,并赋值给变量A  (注意这里可以更换图片的名称,这里是为了简便)

figure, imshow(A), title('原始图像'); % 显示原始图像,并设置窗口标题

结果:

2、对图像进行“红”、“绿”、“蓝”分层提取,并显示

fxy_r = A(:,:,1); % 提取图像A的红色通道  
fxy_g = A(:,:,2); % 提取图像A的绿色通道  
fxy_b = A(:,:,3); % 提取图像A的蓝色通道  
figure, subplot(1,3,1), imshow(fxy_r), title('红色图层'); % 显示红色图层  
subplot(1,3,2), imshow(fxy_g), title('绿色图层'); % 显示绿色图层  
subplot(1,3,3), imshow(fxy_b), title('蓝色图层'); % 显示蓝色图层  

结果:

3.获得图像的3D灰度分布图

 
if size(A, 3) == 3    
    A_gray = rgb2gray(A); % 如果A是RGB图像,则转换为灰度图像  
else    
    A_gray = A; % 如果A已经是灰度图像,则直接使用  
end    
[rows, cols] = size(A_gray); % 获取灰度图像的尺寸  
[X, Y] = meshgrid(1:cols, 1:rows); % 生成网格坐标矩阵  
Z = double(A_gray); % 将灰度图像转换为double类型,用于3D绘图  
figure, surf(X, Y, Z), shading interp, title('3D灰度分布'); % 绘制3D灰度分布图  
 

结果:

4、提取某一行的灰度值图及差值图

  
row_index = 257; % 假设提取第257行  
figure; % 创建一个新的图形窗口  
subplot(2,3,1), plot(fxy_r(row_index,:), '-r'), title('257行红色灰度值'); % 绘制红色通道的灰度值  
subplot(2,3,2), plot(fxy_g(row_index,:), '-g'), title('257行绿色灰度值'); % 绘制绿色通道的灰度值  
subplot(2,3,3), plot(fxy_b(row_index,:), '-b'), title('257行蓝色灰度值'); % 绘制蓝色通道的灰度值  
subplot(2,3,4), plot(fxy_r(row_index,:) - fxy_g(row_index,:), '-k'), title('红-绿差值'); % 绘制红绿差值  
subplot(2,3,5), plot(fxy_r(row_index,:) - fxy_b(row_index,:), '-m'), title('红-蓝差值'); % 绘制红蓝差值  
subplot(2,3,6), plot(fxy_g(row_index,:) - fxy_b(row_index,:), '-c'), title('绿-蓝差值'); % 绘制绿蓝差值  

结果:

5、提取某一列的灰度值图及差值图  

col_index = 128; % 假设我们提取第128列  
figure; % 创建一个新的图形窗口  
subplot(2,3,1), plot(fxy_r(:,col_index), '-r'), title('128列红色灰度值'); % 绘制红色通道的灰度值  
subplot(2,3,2), plot(fxy_g(:,col_index), '-g'), title('128列绿色灰度值'); % 绘制绿色通道的灰度值  
subplot(2,3,3), plot(fxy_b(:,col_index), '-b'), title('128列蓝色灰度值'); % 绘制蓝色通道的灰度值    
subplot(2,3,4), plot(fxy_r(:,col_index) - fxy_g(:,col_index), '-k'), title('红-绿差值'); % 绘制红绿差值  
subplot(2,3,5), plot(fxy_r(:,col_index) - fxy_b(:,col_index), '-m'), title('红-蓝差值'); % 绘制红蓝差值  
subplot(2,3,6), plot(fxy_g(:,col_index) - fxy_b(:,col_index), '-c'), title('绿-蓝差值'); % 绘制绿蓝差值  

结果:

6、Sobel边缘检测  

imgGrayDouble = double(rgb2gray(A)); % 将RGB图像转换为灰度图像,并转换为double类型   
% 垂直Sobel边缘检测  
sobelVertical = imfilter(imgGrayDouble, [-1 0 1; -2 0 2; -1 0 1], 'replicate'); % 应用垂直Sobel滤波器   
% 水平Sobel边缘检测  
sobelHorizontal = imfilter(imgGrayDouble, [-1 -2 -1; 0 0 0; 1 2 1], 'replicate'); % 应用水平Sobel滤波器   
% 显示原始灰度图和边缘检测结果  
figure, imshow(uint8(abs(sobelVertical)), []), title('垂直Sobel边缘检测'); % 显示垂直边缘检测结果  
figure, imshow(uint8(abs(sobelHorizontal)), []), title('水平Sobel边缘检测'); % 显示水平边缘检测结果  
%figure, imshow(imgGrayDouble, []), title('原始灰度图像'); % 可选:显示原始灰度图像 

结果:  

7、计算并显示直方图  

figure; % 创建一个新的图形窗口  
C = rgb2gray(A); % 将RGB图像A转换为灰度图像C  
subplot(4,1,1), imhist(C), title('原图直方图'); % 显示原图的灰度直方图  
subplot(4,1,2), imhist(fxy_r), title('红色通道直方图'); % 显示红色通道的直方图  
subplot(4,1,3), imhist(fxy_g), title('绿色通道直方图'); % 显示绿色通道的直方图  
subplot(4,1,4), imhist(fxy_b), title('蓝色通道直方图'); % 显示蓝色通道的直方图  

结果:

8、高斯平滑处理  

sigma = 1.5; % 高斯核的标准差  
A_smoothed = imgaussfilt(A, sigma); % 对原始图像进行高斯平滑处理  
figure, subplot(1,2,1), imshow(A), title('原始图像'); % 显示原始图像  
subplot(1,2,2), imshow(A_smoothed), title('高斯平滑后的图像'); % 显示高斯平滑后的图像  

结果:

9、Canny边缘检测  

e_canny = edge(rgb2gray(A_smoothed), 'canny'); % 对高斯平滑后的图像进行Canny边缘检测  
figure;
subplot(1,2,1), imshow(A_smoothed), title('高斯平滑后的图像'); % 显示高斯平滑后的图像  
subplot(1,2,2), imshow(e_canny), title('Canny边缘检测'); % 显示Canny边缘检测结果

结果:

完整代码如下:

(这里建议使用matlab2020a/b版本的来运行操作,避免相关函数不包括)

% 1) 输出所选图像  
A = imread('1.png'); % 读取名为'1.png'的图像文件,并赋值给变量A  
% 替换 'your_image.png' 为你的图像文件名  
figure, imshow(A), title('原始图像'); % 显示原始图像,并设置窗口标题  
  
% 2) 对图像进行“红”、“绿”、“蓝”分层提取,并显示  
fxy_r = A(:,:,1); % 提取图像A的红色通道  
fxy_g = A(:,:,2); % 提取图像A的绿色通道  
fxy_b = A(:,:,3); % 提取图像A的蓝色通道  
figure, subplot(1,3,1), imshow(fxy_r), title('红色图层'); % 显示红色图层  
subplot(1,3,2), imshow(fxy_g), title('绿色图层'); % 显示绿色图层  
subplot(1,3,3), imshow(fxy_b), title('蓝色图层'); % 显示蓝色图层  
  
% 3) 获得图像的3D灰度分布图  
if size(A, 3) == 3    
    A_gray = rgb2gray(A); % 如果A是RGB图像,则转换为灰度图像  
else    
    A_gray = A; % 如果A已经是灰度图像,则直接使用  
end    
[rows, cols] = size(A_gray); % 获取灰度图像的尺寸  
[X, Y] = meshgrid(1:cols, 1:rows); % 生成网格坐标矩阵  
Z = double(A_gray); % 将灰度图像转换为double类型,用于3D绘图  
figure, surf(X, Y, Z), shading interp, title('3D灰度分布'); % 绘制3D灰度分布图  
  
% 4) 提取某一行的灰度值图及差值图  
row_index = 257; % 假设提取第257行  
figure; % 创建一个新的图形窗口  
subplot(2,3,1), plot(fxy_r(row_index,:), '-r'), title('257行红色灰度值'); % 绘制红色通道的灰度值  
subplot(2,3,2), plot(fxy_g(row_index,:), '-g'), title('257行绿色灰度值'); % 绘制绿色通道的灰度值  
subplot(2,3,3), plot(fxy_b(row_index,:), '-b'), title('257行蓝色灰度值'); % 绘制蓝色通道的灰度值  
subplot(2,3,4), plot(fxy_r(row_index,:) - fxy_g(row_index,:), '-k'), title('红-绿差值'); % 绘制红绿差值  
subplot(2,3,5), plot(fxy_r(row_index,:) - fxy_b(row_index,:), '-m'), title('红-蓝差值'); % 绘制红蓝差值  
subplot(2,3,6), plot(fxy_g(row_index,:) - fxy_b(row_index,:), '-c'), title('绿-蓝差值'); % 绘制绿蓝差值  
  
% 5) 提取某一列的灰度值图及差值图(类似行,但使用列索引)  
col_index = 128; % 假设我们提取第128列  
figure; % 创建一个新的图形窗口  
subplot(2,3,1), plot(fxy_r(:,col_index), '-r'), title('128列红色灰度值'); % 绘制红色通道的灰度值  
subplot(2,3,2), plot(fxy_g(:,col_index), '-g'), title('128列绿色灰度值'); % 绘制绿色通道的灰度值  
subplot(2,3,3), plot(fxy_b(:,col_index), '-b'), title('128列蓝色灰度值'); % 绘制蓝色通道的灰度值    
subplot(2,3,4), plot(fxy_r(:,col_index) - fxy_g(:,col_index), '-k'), title('红-绿差值'); % 绘制红绿差值  
subplot(2,3,5), plot(fxy_r(:,col_index) - fxy_b(:,col_index), '-m'), title('红-蓝差值'); % 绘制红蓝差值  
subplot(2,3,6), plot(fxy_g(:,col_index) - fxy_b(:,col_index), '-c'), title('绿-蓝差值'); % 绘制绿蓝差值  
  
% 6) Sobel边缘检测  
imgGrayDouble = double(rgb2gray(A)); % 将RGB图像转换为灰度图像,并转换为double类型  
  
% 垂直Sobel边缘检测  
sobelVertical = imfilter(imgGrayDouble, [-1 0 1; -2 0 2; -1 0 1], 'replicate'); % 应用垂直Sobel滤波器  
  
% 水平Sobel边缘检测  
sobelHorizontal = imfilter(imgGrayDouble, [-1 -2 -1; 0 0 0; 1 2 1], 'replicate'); % 应用水平Sobel滤波器  
  
% 显示原始灰度图和边缘检测结果  
figure, imshow(uint8(abs(sobelVertical)), []), title('垂直Sobel边缘检测'); % 显示垂直边缘检测结果  
figure, imshow(uint8(abs(sobelHorizontal)), []), title('水平Sobel边缘检测'); % 显示水平边缘检测结果  
%figure, imshow(imgGrayDouble, []), title('原始灰度图像'); % 可选:显示原始灰度图像  
  
% 7) 计算并显示直方图  
figure; % 创建一个新的图形窗口  
C = rgb2gray(A); % 将RGB图像A转换为灰度图像C  
subplot(4,1,1), imhist(C), title('原图直方图'); % 显示原图的灰度直方图  
subplot(4,1,2), imhist(fxy_r), title('红色通道直方图'); % 显示红色通道的直方图  
subplot(4,1,3), imhist(fxy_g), title('绿色通道直方图'); % 显示绿色通道的直方图  
subplot(4,1,4), imhist(fxy_b), title('蓝色通道直方图'); % 显示蓝色通道的直方图  
  
% 8) 高斯平滑处理  
sigma = 1.5; % 高斯核的标准差  
A_smoothed = imgaussfilt(A, sigma); % 对原始图像进行高斯平滑处理  
figure, subplot(1,2,1), imshow(A), title('原始图像'); % 显示原始图像  
subplot(1,2,2), imshow(A_smoothed), title('高斯平滑后的图像'); % 显示高斯平滑后的图像  
  
% 9) Canny边缘检测  
edges_canny = edge(rgb2gray(A_smoothed), 'canny'); % 对高斯平滑后的图像进行Canny边缘检测  
figure;
subplot(1,2,1), imshow(A_smoothed), title('高斯平滑后的图像'); % 显示高斯平滑后的图像  
subplot(1,2,2), imshow(edges_canny), title('Canny边缘检测'); % 显示Canny边缘检测结果

相关的参考资料如下:

1、Sobel算子:

(1)基于Sobel算子图像边缘检测的MATLAB实现 | Why·Liam·Blog (naaln.com)

(2)Matlab自编函数实现Sobel边缘检测_matlab sobel-CSDN博客

2、matlab中如何做到对所选图像进行高斯平滑处理

(1)【MATLAB 高斯滤波完全指南】:从理论到实战应用,一文搞定 - CSDN文库

(2)MATLAB图像处理:43:用高斯平滑滤波器处理图像 - 知乎 (zhihu.com)

(3)imgaussfilt - 图像的二维高斯滤波 - MATLAB (mathworks.com)

3、matlab中如何做到对平滑后的图像进行Canny边缘检测

(1)Canny边缘检测及matlab实现 - 知乎 (zhihu.com)

(2)边缘检测 - MATLAB & Simulink - MathWorks 中国 (这个方法最简单)

(3)[图像]Canny检测的Matlab实现(含代码)_matlab canny函数-CSDN博客

4、对于图像的任意行或者列的灰度值取值

(1)用MATLAB怎么获取任意像素点的灰度值_matlab灰度值提取-CSDN博客

(2)Matlab图像处理系列——图像点运算和灰度直方图Matlab仿真 - 知乎 (zhihu.com)

参考书籍:

   (1) MATLAB程序设计与应用 第3版  刘卫国著 出版社: 北京:高等教育出版社ISBN:9787040478136

         (哈哈,uu们,咸鱼哥又要开始坚持写文章了,之前的模电实验系列和Arduino系列不是作者不更新,主要是有点忙,后续咸鱼哥也会陆续更新,并会添加嵌入式、UI、opencv/mv、蓝桥杯、光学、电路设计等的文章,还希望大家可以耐心等待,和大家一起加油很快乐,要做励志翻身的咸鱼们哦!)

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace edge { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void open_Click(object sender, EventArgs e) { OpenFileDialog opnDlg = new OpenFileDialog(); opnDlg.Filter = "所有图像文件 | *.bmp; *.pcx; *.png; *.jpg; *.gif;" + "*.tif; *.ico; *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf|" + "位图( *.bmp; *.jpg; *.png;...) | *.bmp; *.pcx; *.png; *.jpg; *.gif; *.tif; *.ico|" + "矢量图( *.wmf; *.eps; *.emf;...) | *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf"; opnDlg.Title = "打开图像文件"; opnDlg.ShowHelp = true; if (opnDlg.ShowDialog() == DialogResult.OK) { curFileName = opnDlg.FileName; try { curBitmap = (Bitmap)Image.FromFile(curFileName); } catch (Exception exp) { MessageBox.Show(exp.Message); } } Invalidate(); } private void close_Click(object sender, EventArgs e) { this.Close(); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; if (curBitmap != null) { g.DrawImage(curBitmap, 160, 20, curBitmap.Width, curBitmap.Height); } } private void mask_Click(object sender, EventArgs e) { if (curBitmap != null) { mask operatorMask = new mask(); if (operatorMask.ShowDialog() == DialogResult.OK) { Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height); System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat); IntPtr ptr = bmpData.Scan0; int bytes = curBitmap.Width * curBitmap.Height; byte[] grayValues = new byte[bytes]; System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes); int thresholding = operatorMask.GetThresholding; byte flagMask = operatorMask.GetMask; double[] tempArray = new double[bytes]; double gradX, gradY, grad; switch (flagMask) { case 0://Roberts for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { gradX = grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] - grayValues[i * curBitmap.Width + j]; gradY = grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] - grayValues[i * curBitmap.Width + ((j + 1) % curBitmap.Width)]; grad = Math.Sqrt(gradX * gradX + gradY * gradY); tempArray[i * curBitmap.Width + j] = grad; } } break; case 1://Prewitt for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { gradX = grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] + grayValues[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] + grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] - grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + (Math.Abs(j - 1) % curBitmap.Width)] - grayValues[i * curBitmap.Width + (Math.Abs(j - 1) % curBitmap.Width)] - grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + (Math.Abs(j - 1) % curBitmap.Width)]; gradY = grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + (Math.Abs(j - 1) % curBitmap.Width)] + grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] + grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] - grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + (Math.Abs(j - 1) % curBitmap.Width)] - grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + j] - grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)]; grad = Math.Sqrt(gradX * gradX + gradY * gradY); tempArray[i * curBitmap.Width + j] = grad; } } break; case 2://Sobel for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { gradX = grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] + 2 * grayValues[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] + grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] - grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - 2 * grayValues[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)]; gradY = grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 2 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] + grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] - grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - 2 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + j] - grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)]; grad = Math.Sqrt(gradX * gradX + gradY * gradY); tempArray[i * curBitmap.Width + j] = grad; } } break; case 3://Laplacian1公式(8.4) for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { grad = grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] + grayValues[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + grayValues[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] + grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + j] - 4 * grayValues[i * curBitmap.Width + j]; tempArray[i * curBitmap.Width + j] = grad; } } break; case 4://Laplacian2公式(8.5) for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { grad = grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] + grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] + grayValues[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + grayValues[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] + grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + j] + grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] - 8 * grayValues[i * curBitmap.Width + j]; tempArray[i * curBitmap.Width + j] = grad; } } break; case 5://Laplacian3公式(8.6) for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { grad = -1 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 2 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] - grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] + 2 * grayValues[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 2 * grayValues[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] - grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 2 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + j] - grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] - 4 * grayValues[i * curBitmap.Width + j]; tempArray[i * curBitmap.Width + j] = grad; } } break; case 6://Kirsch for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { grad = 0; gradX = -5 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] + 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] - 5 * grayValues[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] - 5 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + j] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)]; if (gradX > grad) grad = gradX; gradX = 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] + 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] - 5 * grayValues[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] - 5 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - 5 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + j] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)]; if (gradX > grad) grad = gradX; gradX = 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] + 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] + 3 * grayValues[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] - 5 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - 5 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + j] - 5 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)]; if (gradX > grad) grad = gradX; gradX = 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] + 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] + 3 * grayValues[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - 5 * grayValues[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - 5 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + j] - 5 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)]; if (gradX > grad) grad = gradX; gradX = 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] - 5 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] + 3 * grayValues[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - 5 * grayValues[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + j] - 5 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)]; if (gradX > grad) grad = gradX; gradX = 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - 5 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] - 5 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] + 3 * grayValues[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - 5 * grayValues[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + j] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)]; if (gradX > grad) grad = gradX; gradX = -5 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - 5 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] - 5 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] + 3 * grayValues[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + j] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)]; if (gradX > grad) grad = gradX; gradX = -5 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - 5 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] + 3 * grayValues[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] - 5 * grayValues[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + j] + 3 * grayValues[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)]; if (gradX > grad) grad = gradX; tempArray[i * curBitmap.Width + j] = grad; } } break; default: MessageBox.Show("无效!"); break; } if (thresholding == 0)//不进行阈值处理 { for (int i = 0; i < bytes; i++) { if (tempArray[i] < 0) grayValues[i] = 0; else { if (tempArray[i] > 255) grayValues[i] = 255; else grayValues[i] = Convert.ToByte(tempArray[i]); } } } else//阈值处理,生成二值边缘图像 { if (flagMask == 3 || flagMask == 4 || flagMask == 5) { zerocross(ref tempArray, out grayValues, thresholding); } else { for (int i = 0; i < bytes; i++) { if (tempArray[i] > thresholding) grayValues[i] = 255; else grayValues[i] = 0; } } } System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes); curBitmap.UnlockBits(bmpData); } Invalidate(); } } private void gaussian_Click(object sender, EventArgs e) { if (curBitmap != null) { gaussian gaussFilter = new gaussian(); if (gaussFilter.ShowDialog() == DialogResult.OK) { Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height); System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat); IntPtr ptr = bmpData.Scan0; int bytes = curBitmap.Width * curBitmap.Height; byte[] grayValues = new byte[bytes]; System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes); double thresholding = gaussFilter.GetThresholding; double sigma = gaussFilter.GetSigma; bool flag = gaussFilter.GetFlag; double[] filt, tempArray; createFilter(out filt, sigma, flag); conv2(ref grayValues, ref filt, out tempArray); zerocross(ref tempArray, out grayValues, thresholding); System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes); curBitmap.UnlockBits(bmpData); } Invalidate(); } } private void zerocross(ref double[] inputImage, out byte[] outImage, double thresh) { outImage = new byte[curBitmap.Width * curBitmap.Height]; for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { if (inputImage[i * curBitmap.Width + j] < 0 && inputImage[((i + 1) % curBitmap.Height) * curBitmap.Width + j] > 0 && Math.Abs(inputImage[i * curBitmap.Width + j] - inputImage[((i + 1) % curBitmap.Height) * curBitmap.Width + j]) > thresh) { outImage[i * curBitmap.Width + j] = 255; } else if (inputImage[i * curBitmap.Width + j] < 0 && inputImage[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] > 0 && Math.Abs(inputImage[i * curBitmap.Width + j] - inputImage[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j]) > thresh) { outImage[i * curBitmap.Width + j] = 255; } else if (inputImage[i * curBitmap.Width + j] < 0 && inputImage[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] > 0 && Math.Abs(inputImage[i * curBitmap.Width + j] - inputImage[i * curBitmap.Width + ((j + 1) % curBitmap.Width)]) > thresh) { outImage[i * curBitmap.Width + j] = 255; } else if (inputImage[i * curBitmap.Width + j] < 0 && inputImage[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] > 0 && Math.Abs(inputImage[i * curBitmap.Width + j] - inputImage[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)]) > thresh) { outImage[i * curBitmap.Width + j] = 255; } else if (inputImage[i * curBitmap.Width + j] == 0) { if (inputImage[((i + 1) % curBitmap.Height) * curBitmap.Width + j] > 0 && inputImage[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] < 0 && Math.Abs(inputImage[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] - inputImage[((i + 1) % curBitmap.Height) * curBitmap.Width + j]) > 2 * thresh) { outImage[i * curBitmap.Width + j] = 255; } else if (inputImage[((i + 1) % curBitmap.Height) * curBitmap.Width + j] < 0 && inputImage[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] > 0 && Math.Abs(inputImage[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] - inputImage[((i + 1) % curBitmap.Height) * curBitmap.Width + j]) > 2 * thresh) { outImage[i * curBitmap.Width + j] = 255; } else if (inputImage[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] > 0 && inputImage[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] < 0 && Math.Abs(inputImage[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] - inputImage[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)]) > 2 * thresh) { outImage[i * curBitmap.Width + j] = 255; } else if (inputImage[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] < 0 && inputImage[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] > 0 && Math.Abs(inputImage[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] - inputImage[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)]) > 2 * thresh) { outImage[i * curBitmap.Width + j] = 255; } else { outImage[i * curBitmap.Width + j] = 0; } } else { outImage[i * curBitmap.Width + j] = 0; } } } } private void createFilter(out double[] filter, double sigma, bool lod) { double std2 = 2 * sigma * sigma; int radius = Convert.ToInt16(Math.Ceiling(3 * sigma)); int filterWidth = 2 * radius + 1; filter = new double[filterWidth * filterWidth]; double sum = 0, average = 0; if (lod == false) { for (int i = 0; i < radius; i++) { for (int j = 0; j < radius; j++) { int xx = (j - radius) * (j - radius); int yy = (i - radius) * (i - radius); filter[i * filterWidth + j] = (xx + yy - std2) * Math.Exp(-(xx + yy) / std2); sum += 4 * filter[i * filterWidth + j]; } } for (int i = 0; i < radius; i++) { int xx = (i - radius) * (i - radius); filter[i * filterWidth + radius] = (xx - std2) * Math.Exp(-xx / std2); sum += 2 * filter[i * filterWidth + radius]; } for (int j = 0; j < radius; j++) { int yy = (j - radius) * (j - radius); filter[radius * filterWidth + j] = (yy - std2) * Math.Exp(-yy / std2); sum += 2 * filter[radius * filterWidth + j]; } filter[radius * filterWidth + radius] = -std2; sum += filter[radius * filterWidth + radius]; average = sum / filter.Length; for (int i = 0; i < radius; i++) { for (int j = 0; j < radius; j++) { filter[i * filterWidth + j] = filter[i * filterWidth + j] - average; filter[filterWidth - 1 - j + i * filterWidth] = filter[i * filterWidth + j]; filter[filterWidth - 1 - j + (filterWidth - 1 - i) * filterWidth] = filter[i * filterWidth + j]; filter[j + (filterWidth - 1 - i) * filterWidth] = filter[i * filterWidth + j]; } } for (int i = 0; i < radius; i++) { filter[i * filterWidth + radius] = filter[i * filterWidth + radius] - average; filter[(filterWidth - 1 - i) * filterWidth + radius] = filter[i * filterWidth + radius]; } for (int j = 0; j < radius; j++) { filter[radius * filterWidth + j] = filter[radius * filterWidth + j] - average; filter[radius * filterWidth + filterWidth - 1 - j] = filter[radius * filterWidth + j]; } filter[radius * filterWidth + radius] = filter[radius * filterWidth + radius] - average; } else { for (int i = 0; i < radius; i++) { for (int j = 0; j < radius; j++) { int xx = (j - radius) * (j - radius); int yy = (i - radius) * (i - radius); filter[i * filterWidth + j] = 1.6 * Math.Exp(-(xx + yy) * 1.6 * 1.6 / std2) / sigma - Math.Exp(-(xx + yy) / std2) / sigma; sum += 4 * filter[i * filterWidth + j]; } } for (int i = 0; i < radius; i++) { int xx = (i - radius) * (i - radius); filter[i * filterWidth + radius] = 1.6 * Math.Exp(-xx * 1.6 * 1.6 / std2) / sigma - Math.Exp(-xx / std2) / sigma; sum += 2 * filter[i * filterWidth + radius]; } for (int j = 0; j < radius; j++) { int yy = (j - radius) * (j - radius); filter[radius * filterWidth + j] = 1.6 * Math.Exp(-yy * 1.6 * 1.6 / std2) / sigma - Math.Exp(-yy / std2) / sigma; sum += 2 * filter[radius * filterWidth + j]; } filter[radius * filterWidth + radius] = 1.6 / sigma - 1 / sigma; sum += filter[radius * filterWidth + radius]; average = sum / filter.Length; for (int i = 0; i < radius; i++) { for (int j = 0; j < radius; j++) { filter[i * filterWidth + j] = filter[i * filterWidth + j] - average; filter[filterWidth - 1 - j + i * filterWidth] = filter[i * filterWidth + j]; filter[filterWidth - 1 - j + (filterWidth - 1 - i) * filterWidth] = filter[i * filterWidth + j]; filter[j + (filterWidth - 1 - i) * filterWidth] = filter[i * filterWidth + j]; } } for (int i = 0; i < radius; i++) { filter[i * filterWidth + radius] = filter[i * filterWidth + radius] - average; filter[(filterWidth - 1 - i) * filterWidth + radius] = filter[i * filterWidth + radius]; } for (int j = 0; j < radius; j++) { filter[radius * filterWidth + j] = filter[radius * filterWidth + j] - average; filter[radius * filterWidth + filterWidth - 1 - j] = filter[radius * filterWidth + j]; } filter[radius * filterWidth + radius] = filter[radius * filterWidth + radius] - average; } } private void conv2(ref byte[] inputImage, ref double[] mask, out double[] outImage) { int windWidth = Convert.ToInt16(Math.Sqrt(mask.Length)); int radius = windWidth / 2; double temp; outImage = new double[curBitmap.Width * curBitmap.Height]; for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { temp = 0; for (int x = -radius; x <= radius; x++) { for (int y = -radius; y <= radius; y++) { temp += inputImage[((Math.Abs(i + x)) % curBitmap.Height) * curBitmap.Width + (Math.Abs(j + y)) % curBitmap.Width] * mask[(x + radius) * windWidth + y + radius]; } } outImage[i * curBitmap.Width + j] = temp; } } } private void canny_Click(object sender, EventArgs e) { if (curBitmap != null) { canny cannyOp = new canny(); if (cannyOp.ShowDialog() == DialogResult.OK) { Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height); System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat); IntPtr ptr = bmpData.Scan0; int bytes = curBitmap.Width * curBitmap.Height; byte[] grayValues = new byte[bytes]; System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes); byte[] thresholding = new byte[2]; thresholding = cannyOp.GetThresh; double sigma = cannyOp.GetSigma; double[] tempArray;// = new double[bytes]; double[] tempImage = new double[bytes]; double[] grad = new double[bytes]; byte[] aLabel = new byte[bytes]; double[] edgeMap = new double[bytes]; Array.Clear(edgeMap, 0, bytes); double gradX, gradY, angle; int rad = Convert.ToInt16(Math.Ceiling(3 * sigma)); for (int i = 0; i < bytes; i++) tempImage[i] = Convert.ToDouble(grayValues[i]); gaussSmooth(tempImage, out tempArray, sigma); for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { gradX = tempArray[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] + 2 * tempArray[i * curBitmap.Width + ((j + 1) % curBitmap.Width)] + tempArray[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] - tempArray[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - 2 * tempArray[i * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - tempArray[((i + 1) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)]; gradY = tempArray[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] + 2 * tempArray[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] + tempArray[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] - tempArray[((i + 1) % curBitmap.Height) * curBitmap.Width + ((Math.Abs(j - 1)) % curBitmap.Width)] - 2 * tempArray[((i + 1) % curBitmap.Height) * curBitmap.Width + j] - tempArray[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)]; grad[i * curBitmap.Width + j] = Math.Sqrt(gradX * gradX + gradY * gradY); angle = Math.Atan2(gradY, gradX); if ((angle >= -1.178097 && angle < 1.178097) || angle >= 2.748894 || angle < -2.748894) aLabel[i * curBitmap.Width + j] = 0; else if ((angle >= 0.392699 && angle < 1.178097) || (angle >= -2.748894 && angle < -1.963495)) aLabel[i * curBitmap.Width + j] = 1; else if ((angle >= -1.178097 && angle < -0.392699) || (angle >= 1.963495 && angle < 2.748894)) aLabel[i * curBitmap.Width + j] = 2; else aLabel[i * curBitmap.Width + j] = 3; } } for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { switch (aLabel[i * curBitmap.Width + j]) { case 3://水平方向 if (grad[i * curBitmap.Width + j] > grad[((Math.Abs(i - 1))%curBitmap.Height) * curBitmap.Width + j] && grad[i * curBitmap.Width + j] > grad[((i + 1)%curBitmap.Height) * curBitmap.Width + j]) edgeMap[i * curBitmap.Width + j] = grad[i * curBitmap.Width + j]; break; case 2://正45度方向 if (grad[i * curBitmap.Width + j] > grad[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + (Math.Abs(j - 1) % curBitmap.Width)] && grad[i * curBitmap.Width + j] > grad[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)]) edgeMap[i * curBitmap.Width + j] = grad[i * curBitmap.Width + j]; break; case 1://负45度方向 if (grad[i * curBitmap.Width + j] > grad[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] && grad[i * curBitmap.Width + j] > grad[((i + 1) % curBitmap.Height) * curBitmap.Width + (Math.Abs(j - 1) % curBitmap.Width)]) edgeMap[i * curBitmap.Width + j] = grad[i * curBitmap.Width + j]; break; case 0://垂直方向 if (grad[i * curBitmap.Width + j] > grad[i * curBitmap.Width + (Math.Abs(j - 1) % curBitmap.Width)] && grad[i * curBitmap.Width + j] > grad[i * curBitmap.Width + ((j + 1) % curBitmap.Width)]) edgeMap[i * curBitmap.Width + j] = grad[i * curBitmap.Width + j]; break; default: return; } } } Array.Clear(grayValues, 0, bytes); for (int i = 0; i < curBitmap.Height; i++) { for (int j =0; j < curBitmap.Width; j++) { if (edgeMap[i * curBitmap.Width + j] > thresholding[0]) { grayValues[i * curBitmap.Width + j] = 255; traceEdge(i, j, edgeMap, ref grayValues, thresholding[1]); } } } System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes); curBitmap.UnlockBits(bmpData); } Invalidate(); } } private void gaussSmooth(double[] inputImage, out double[] outputImage, double sigma) { double std2 = 2 * sigma * sigma; int radius = Convert.ToInt16(Math.Ceiling(3 * sigma)); int filterWidth = 2 * radius + 1; double[] filter = new double[filterWidth]; outputImage = new double[inputImage.Length]; int length = Convert.ToInt16(Math.Sqrt(inputImage.Length)); double[] tempImage = new double[inputImage.Length]; double sum = 0; for (int i = 0; i < filterWidth; i++) { int xx = (i - radius) * (i - radius); filter[i] = Math.Exp(-xx / std2); sum += filter[i]; } for (int i = 0; i < filterWidth; i++) { filter[i] = filter[i] / sum; } for (int i = 0; i < length; i++) { for (int j = 0; j < length; j++) { double temp = 0; for (int k = -radius; k <= radius; k++) { int rem = (Math.Abs(j + k)) % length; temp += inputImage[i * length + rem] * filter[k + radius]; } tempImage[i * length + j] = temp; } } for (int j = 0; j < length; j++) { for (int i = 0; i < length; i++) { double temp = 0; for (int k = -radius; k <= radius; k++) { int rem = (Math.Abs(i + k)) % length; temp += tempImage[rem * length + j] * filter[k + radius]; } outputImage[i * length + j] = temp; } } } private void traceEdge(int k, int l, double[] inputImage, ref byte[] outputImage, byte thrLow) { int[] kOffset = new int[] { 1, 1, 0, -1, -1, -1, 0, 1 }; int[] lOffset = new int[] { 0, 1, 1, 1, 0, -1, -1, -1 }; int kk, ll; for (int p = 0; p < 8; p++) { kk = k + kOffset[p]; kk = Math.Abs(kk) % curBitmap.Height; ll = l + lOffset[p]; ll = Math.Abs(ll) % curBitmap.Width; if (outputImage[ll * curBitmap.Width + kk] != 255) { if (inputImage[ll * curBitmap.Width + kk] > thrLow) { outputImage[ll * curBitmap.Width + kk] = 255; traceEdge(ll, kk, inputImage, ref outputImage, thrLow); } } } } private void morph_Click(object sender, EventArgs e) { if (curBitmap != null) { morphologic grayMor = new morphologic(); if (grayMor.ShowDialog() == DialogResult.OK) { Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height); System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat); IntPtr ptr = bmpData.Scan0; int bytes = curBitmap.Width * curBitmap.Height; byte[] grayValues = new byte[bytes]; System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes); byte[] tempArray1 = new byte[bytes]; byte[] tempArray2 = new byte[bytes]; bool flag = grayMor.GetMethod; double thresh = grayMor.GetThresh; byte[] struEle = new byte[25]; struEle = grayMor.GetStruction; int temp; tempArray1 = grayDelation(grayValues, struEle, curBitmap.Height, curBitmap.Width); tempArray2 = grayErode(grayValues, struEle, curBitmap.Height, curBitmap.Width); for (int i = 0; i < bytes; i++) { if (flag == false) temp = (tempArray1[i] - tempArray2[i]) / 2; else temp = (tempArray1[i] + tempArray2[i] - 2 * grayValues[i]) / 2; if (temp > thresh) grayValues[i] = 255; else grayValues[i] = 0; } System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes); curBitmap.UnlockBits(bmpData); } Invalidate(); } } private byte[] grayDelation(byte[] grayImage, byte[] se, int tHeight, int tWidth) { byte[] tempImage = new byte[grayImage.Length]; for (int i = 0; i < tHeight; i++) { for (int j = 0; j < tWidth; j++) { int[] cou = new int[]{grayImage[((Math.Abs(i - 2)) % tHeight) * tWidth + (Math.Abs(j - 2)) % tWidth] * se[0], grayImage[((Math.Abs(i - 2)) % tHeight) * tWidth + (Math.Abs(j - 1)) % tWidth] * se[1], grayImage[((Math.Abs(i - 2)) % tHeight) * tWidth + j] * se[2], grayImage[((Math.Abs(i - 2)) % tHeight) * tWidth + ((j + 1) % tWidth)] * se[3], grayImage[((Math.Abs(i - 2)) % tHeight) * tWidth + ((j + 2) % tWidth)] * se[4], grayImage[((Math.Abs(i - 1)) % tHeight) * tWidth + (Math.Abs(j - 2) % tWidth)] * se[5], grayImage[((Math.Abs(i - 1)) % tHeight) * tWidth + (Math.Abs(j - 1) % tWidth)] * se[6], grayImage[((Math.Abs(i - 1)) % tHeight) * tWidth + j] * se[7], grayImage[((Math.Abs(i - 1)) % tHeight) * tWidth + ((j + 1) % tWidth)] * se[8], grayImage[((Math.Abs(i - 1)) % tHeight) * tWidth + ((j + 2) % tWidth)] * se[9], grayImage[i * tWidth + (Math.Abs(j - 2) % tWidth)] * se[10], grayImage[i * tWidth + (Math.Abs(j - 1) % tWidth)] * se[11], grayImage[i * tWidth + j] * se[12], grayImage[i * tWidth + ((j + 1) % tWidth)] * se[13], grayImage[i * tWidth + ((j + 2) % tWidth)] * se[14], grayImage[((i + 1) % tHeight) * tWidth + (Math.Abs(j - 2) % tWidth)] * se[15], grayImage[((i + 1) % tHeight) * tWidth + (Math.Abs(j - 1) % tWidth)] * se[16], grayImage[((i + 1) % tHeight) * tWidth + j] * se[17], grayImage[((i + 1) % tHeight) * tWidth + ((j + 1) % tWidth)] * se[18], grayImage[((i + 1) % tHeight) * tWidth + ((j + 2) % tWidth)] * se[19], grayImage[((i + 2) % tHeight) * tWidth + (Math.Abs(j - 2) % tWidth)] * se[20], grayImage[((i + 2) % tHeight) * tWidth + (Math.Abs(j - 1) % tWidth)] * se[21], grayImage[((i + 2) % tHeight) * tWidth + j] * se[22], grayImage[((i + 2) % tHeight) * tWidth + ((j + 1) % tWidth)] * se[23], grayImage[((i + 2) % tHeight) * tWidth + ((j + 2) % tWidth)] * se[24]}; int maxim = cou[0]; for (int k = 1; k < 25; k++) { if (cou[k] > maxim) { maxim = cou[k]; } } tempImage[i * tWidth + j] = (byte)maxim; } } return tempImage; } private byte[] grayErode(byte[] grayImage, byte[] se, int tHeight, int tWidth) { byte[] tempImage = new byte[grayImage.Length]; byte[] tempSe = new byte[25]; tempSe = (byte[])se.Clone(); for (int k = 0; k < 25; k++) { if (tempSe[k] == 0) tempSe[k] = 255; } for (int i = 0; i < tHeight; i++) { for (int j = 0; j < tWidth; j++) { int[] cou = new int[]{grayImage[((Math.Abs(i - 2)) % tHeight) * tWidth + (Math.Abs(j - 2)) % tWidth] * tempSe[0], grayImage[((Math.Abs(i - 2)) % tHeight) * tWidth + (Math.Abs(j - 1)) % tWidth] * tempSe[1], grayImage[((Math.Abs(i - 2)) % tHeight) * tWidth + j] * tempSe[2], grayImage[((Math.Abs(i - 2)) % tHeight) * tWidth + ((j + 1) % tWidth)] * tempSe[3], grayImage[((Math.Abs(i - 2)) % tHeight) * tWidth + ((j + 2) % tWidth)] * tempSe[4], grayImage[((Math.Abs(i - 1)) % tHeight) * tWidth + (Math.Abs(j - 2) % tWidth)] * tempSe[5], grayImage[((Math.Abs(i - 1)) % tHeight) * tWidth + (Math.Abs(j - 1) % tWidth)] * tempSe[6], grayImage[((Math.Abs(i - 1)) % tHeight) * tWidth + j] * tempSe[7], grayImage[((Math.Abs(i - 1)) % tHeight) * tWidth + ((j + 1) % tWidth)] * tempSe[8], grayImage[((Math.Abs(i - 1)) % tHeight) * tWidth + ((j + 2) % tWidth)] * tempSe[9], grayImage[i * tWidth + (Math.Abs(j - 2) % tWidth)] * tempSe[10], grayImage[i * tWidth + (Math.Abs(j - 1) % tWidth)] * tempSe[11], grayImage[i * tWidth + j] * tempSe[12], grayImage[i * tWidth + ((j + 1) % tWidth)] * tempSe[13], grayImage[i * tWidth + ((j + 2) % tWidth)] * tempSe[14], grayImage[((i + 1) % tHeight) * tWidth + (Math.Abs(j - 2) % tWidth)] * tempSe[15], grayImage[((i + 1) % tHeight) * tWidth + (Math.Abs(j - 1) % tWidth)] * tempSe[16], grayImage[((i + 1) % tHeight) * tWidth + j] * tempSe[17], grayImage[((i + 1) % tHeight) * tWidth + ((j + 1) % tWidth)] * tempSe[18], grayImage[((i + 1) % tHeight) * tWidth + ((j + 2) % tWidth)] * tempSe[19], grayImage[((i + 2) % tHeight) * tWidth + (Math.Abs(j - 2) % tWidth)] * tempSe[20], grayImage[((i + 2) % tHeight) * tWidth + (Math.Abs(j - 1) % tWidth)] * tempSe[21], grayImage[((i + 2) % tHeight) * tWidth + j] * tempSe[22], grayImage[((i + 2) % tHeight) * tWidth + ((j + 1) % tWidth)] * tempSe[23], grayImage[((i + 2) % tHeight) * tWidth + ((j + 2) % tWidth)] * tempSe[24]}; int minimum = cou[0]; for (int k = 1; k < 25; k++) { if (cou[k] < minimum) { minimum = cou[k]; } } tempImage[i * tWidth + j] = (byte)minimum; } } return tempImage; } private void wavelet_Click(object sender, EventArgs e) { if (curBitmap != null) { wvl wavelet = new wvl(); if (wavelet.ShowDialog() == DialogResult.OK) { Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height); System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat); IntPtr ptr = bmpData.Scan0; int bytes = curBitmap.Width * curBitmap.Height; byte[] grayValues = new byte[bytes]; System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes); double[] tempArray1 = new double[bytes]; double[] tempArray2 = new double[bytes]; double[] tempArray3 = new double[bytes]; double[] gradX = new double[bytes]; double[] gradY = new double[bytes]; byte multiscale = wavelet.GetScale; byte[] thresholding = new byte[2]; thresholding = wavelet.GetThresh; for (int i = 0; i < bytes; i++) { tempArray1[i] = Convert.ToDouble(grayValues[i]); } for (int z = 0; z <= multiscale; z++) { double[] p = null; double[] q = null; switch (z) { case 0: p = new double[] { 0.125, 0.375, 0.375, 0.125 }; q = new double[] { -2, 2 }; break; case 1: p = new double[] { 0.125, 0, 0.375, 0, 0.375, 0, 0.125 }; q = new double[] { -2, 0, 2 }; break; case 2: p = new double[] { 0.125, 0, 0, 0, 0.375, 0, 0, 0, 0.375, 0, 0, 0, 0.125 }; q = new double[] { -2, 0, 0, 0, 2 }; break; case 3: p = new double[] { 0.125, 0, 0, 0, 0, 0, 0, 0, 0.375, 0, 0, 0, 0, 0, 0, 0, 0.375, 0, 0, 0, 0, 0, 0, 0, 0.125 }; q = new double[] { -2, 0, 0, 0, 0, 0, 0, 0, 2 }; break; default: return; } int coff = Convert.ToInt16(Math.Pow(2, z) - 1); for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { double[] scl = new double[curBitmap.Width]; double[] wvl = new double[curBitmap.Width]; int temp; scl[j] = 0.0; wvl[j] = 0.0; for (int x = -2 - 2 * coff; x < p.Length - 2 - 2 * coff; x++) { temp = (Math.Abs(j + x)) % curBitmap.Width; scl[j] += p[1 + coff - x] * tempArray1[i * curBitmap.Width + temp]; } for (int x = -1 - coff; x < q.Length - 1 - coff; x++) { temp = (Math.Abs(j + x)) % curBitmap.Width; wvl[j] += q[-x] * tempArray1[i * curBitmap.Width + temp]; } tempArray2[i * curBitmap.Width + j] = scl[j]; gradX[i * curBitmap.Width + j] = wvl[j]; } } for (int i = 0; i < curBitmap.Width; i++) { for (int j = 0; j < curBitmap.Height; j++) { double[] scl = new double[curBitmap.Height]; double[] wvl = new double[curBitmap.Height]; int temp; scl[j] = 0.0; wvl[j] = 0.0; for (int x = -2 - 2 * coff; x < p.Length - 2 - 2 * coff; x++) { temp = (Math.Abs(j + x)) % curBitmap.Height; scl[j] += p[1 + coff - x] * tempArray2[temp * curBitmap.Width + i]; } for (int x = -1 - coff; x < q.Length - 1 - coff; x++) { temp = (Math.Abs(j + x)) % curBitmap.Height; wvl[j] += q[-x] * tempArray1[temp * curBitmap.Width + i]; } tempArray3[j * curBitmap.Width + i] = scl[j]; gradY[j * curBitmap.Width + i] = wvl[j]; } } tempArray1 = (double[])tempArray3.Clone(); } double angle; for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { tempArray1[i * curBitmap.Width + j] = Math.Sqrt(gradX[i * curBitmap.Width + j] * gradX[i * curBitmap.Width + j] + gradY[i * curBitmap.Width + j] * gradY[i * curBitmap.Width + j]); angle = Math.Atan2(gradY[i * curBitmap.Width + j], gradX[i * curBitmap.Width + j]); if ((angle >= -1.178097 && angle < 1.178097) || angle >= 2.748894 || angle < -2.748894) tempArray2[i * curBitmap.Width + j] = 0; else if ((angle >= 0.392699 && angle < 1.178097) || (angle >= -2.748894 && angle < -1.963495)) tempArray2[i * curBitmap.Width + j] = 1; else if ((angle >= -1.178097 && angle < -0.392699) || (angle >= 1.963495 && angle < 2.748894)) tempArray2[i * curBitmap.Width + j] = 2; else tempArray2[i * curBitmap.Width + j] = 3; } } Array.Clear(tempArray3, 0, bytes); for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { switch (Convert.ToInt16(tempArray2[i * curBitmap.Width + j])) { case 3://水平方向 if (tempArray1[i * curBitmap.Width + j] > tempArray1[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + j] && tempArray1[i * curBitmap.Width + j] > tempArray1[((i + 1) % curBitmap.Height) * curBitmap.Width + j]) tempArray3[i * curBitmap.Width + j] = tempArray1[i * curBitmap.Width + j]; break; case 1://正45度方向 if (tempArray1[i * curBitmap.Width + j] > tempArray1[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + (Math.Abs(j - 1) % curBitmap.Width)] && tempArray1[i * curBitmap.Width + j] > tempArray1[((i + 1) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)]) tempArray3[i * curBitmap.Width + j] = tempArray1[i * curBitmap.Width + j]; break; case 2://负45度方向 if (tempArray1[i * curBitmap.Width + j] > tempArray1[((Math.Abs(i - 1)) % curBitmap.Height) * curBitmap.Width + ((j + 1) % curBitmap.Width)] && tempArray1[i * curBitmap.Width + j] > tempArray1[((i + 1) % curBitmap.Height) * curBitmap.Width + (Math.Abs(j - 1) % curBitmap.Width)]) tempArray3[i * curBitmap.Width + j] = tempArray1[i * curBitmap.Width + j]; break; case 0://垂直方向 if (tempArray1[i * curBitmap.Width + j] > tempArray1[i * curBitmap.Width + (Math.Abs(j - 1) % curBitmap.Width)] && tempArray1[i * curBitmap.Width + j] > tempArray1[i * curBitmap.Width + ((j + 1) % curBitmap.Width)]) tempArray3[i * curBitmap.Width + j] = tempArray1[i * curBitmap.Width + j]; break; default: return; } } } Array.Clear(grayValues, 0, bytes); for (int i = 0; i < curBitmap.Height; i++) { for (int j = 0; j < curBitmap.Width; j++) { if (tempArray3[i * curBitmap.Width + j] > thresholding[0]) { grayValues[i * curBitmap.Width + j] = 255; traceEdge(i, j, tempArray3, ref grayValues, thresholding[1]); } } } System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes); curBitmap.UnlockBits(bmpData); } Invalidate(); } } private void pyramid_Click(object sender, EventArgs e) { if (curBitmap != null) { int series = Convert.ToInt16(Math.Log(curBitmap.Width, 2)); glp pyramid = new glp(series); if (pyramid.ShowDialog() == DialogResult.OK) { Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height); System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat); IntPtr ptr = bmpData.Scan0; int bytes = curBitmap.Width * curBitmap.Height; byte[] grayValues = new byte[bytes]; System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes); double thresh = pyramid.GetThresh; byte level = pyramid.GetLevel; double sigma = pyramid.GetSigma; double[][] pyramidImage = new double[level + 1][]; double[][] passImage = new double[level + 1][]; int levelBytes = bytes; for (int k = 0; k < level + 1; k++) { passImage[k] = new double[levelBytes]; pyramidImage[k] = new double[levelBytes]; levelBytes = levelBytes / 4; } for (int i = 0; i < bytes; i++) pyramidImage[0][i] = Convert.ToDouble(grayValues[i]); for (int k = 0; k < level; k++) { double[] tempImage = null; gaussSmooth(pyramidImage[k], out tempImage, sigma); int coff = pyramidImage[k].Length; for (int i = 0; i < coff; i++) { passImage[k][i] = pyramidImage[k][i] - tempImage[i]; int div = i / Convert.ToInt16(Math.Sqrt(coff)); int rem = i % Convert.ToInt16(Math.Sqrt(coff)); if (div % 2 == 0 && rem % 2 == 0) { int j = (int)((div / 2) * Math.Sqrt(pyramidImage[k + 1].Length) + rem / 2); pyramidImage[k + 1][j] = tempImage[i]; } } } for (int k = level - 1; k >= 0; k--) { int coff = pyramidImage[k].Length; for (int i = 0; i < coff; i++) { int div = i / Convert.ToInt16(Math.Sqrt(coff)); int rem = i % Convert.ToInt16(Math.Sqrt(coff)); int j = (int)((div / 2) * Math.Sqrt(pyramidImage[k + 1].Length) + rem / 2); if (div % 2 == 0 && rem % 2 == 0) pyramidImage[k][i] = pyramidImage[k + 1][j]; else pyramidImage[k][i] = 0; } double[] tempImage = null; gaussSmooth(pyramidImage[k], out tempImage, 1); for (int i = 0; i < coff; i++) pyramidImage[k][i] = tempImage[i] + passImage[k][i]; } zerocross(ref pyramidImage[0], out grayValues,thresh); System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes); curBitmap.UnlockBits(bmpData); } Invalidate(); } } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值