C# 影像特征点提取
发布时间
阅读量:
阅读量
版权所有 详情咨询qq 849495327
内容和要求如下:
任务:提取一幅数字影像中的特征点
内容:使用Moravec算子编写程序,从一幅数字影像中自动提取出50个以上的特征点
要求:程序能读取数字图像、在窗口中显示整幅图像、在图像中显示所提取的特征点(+),并列表显示各特征点的像素坐标。
算法流程及计算原理
1.选取一个合理的邻域遍历图像,这里是5*5邻域的。在邻域中依次计算,垂直,水平,对角与反对角四个相邻像素灰度的差的平方和,作为该邻域特征值。
大致就是下面这个样子:

公式:

这里k是窗口的半径。
2.从四个特征值中选最小的值作为该像素初次候选特征值。
公式:

3.设定一个阈值,将大于该阈值初次候选特征值的选为二次候选特征值。
4.设定一个邻域,将该邻域最大的二次候选特征值作为最终要选择的特征值。
界面调试



主要界面的代码:
FORM1:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace shuzituxiangchuli
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private string curFilename;
private System.Drawing.Bitmap curbitmap;
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openglg = new OpenFileDialog();
openglg.Filter = "所有图像文件|*.bmp;*.png;*.pcx;*.jpg;*.gif;*.tif;*.ico";
openglg.Title = "打开图像文件";
openglg.ShowHelp = true;
if (openglg.ShowDialog() == DialogResult.OK)
{
curFilename = openglg.FileName;
try
{
curbitmap = (Bitmap)Image.FromFile(curFilename);
}
catch (Exception exp)
{
MessageBox.Show(exp.Message);
}
}
Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = this.panel1.CreateGraphics();
if (curbitmap != null)
{
int x, y;
x = curbitmap.Width;
y = curbitmap.Height;
while (x > this.Width - 160 && y > this.Height - 20)
{
x = x / 2;
y = y / 2;
}
g.DrawImage(curbitmap, 160, 20, x, y);
//g.DrawImage(curbitmap, 160, 20, curbitmap.Width, curbitmap.Height);
}
g.Dispose();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
//this.panel1.Left = 10;
this.panel1.BackColor = Color.CadetBlue;
}
private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
{
//curbitmap = new Bitmap(curbitmap, new Size(curbitmap.Width / 2, curbitmap.Height / 2));
Graphics g = this.panel1.CreateGraphics();
g.Clear(this.panel1.BackColor);
}
private void Form1_Scroll(object sender, ScrollEventArgs e)
{
}
private void button4_Click(object sender, EventArgs e)
{
FrmhistR f = new FrmhistR(curbitmap);
f.Show();
FrmhistG G = new FrmhistG(curbitmap);
G.Show();
FrmhistB B = new FrmhistB(curbitmap);
B.Show();
}
private void button5_Click(object sender, EventArgs e)
{
if (curbitmap != null)
{
Frmliner finearfrom = new Frmliner();
if (finearfrom.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 = 3 * curbitmap.Width * curbitmap.Height;
byte[] grayValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
int temp = 0;
double a = Convert.ToDouble(finearfrom.Getscaling);
double b = Convert.ToDouble(finearfrom.Getoffset);
for (int i = 0; i < bytes; i++)
{
temp = (int)(a * grayValues[i] + b + 0.5);
if (temp > 255)
{
grayValues[i] = 255;
}
else
if (temp < 0)
grayValues[i] = 0;
else
grayValues[i] = (byte)temp;
}
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
curbitmap.UnlockBits(bmpdata);
}
Invalidate();
}
}
private void button6_Click(object sender, EventArgs e)
{
if (curbitmap != null)
{
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 = 2 * curbitmap.Width * curbitmap.Height;
byte[] grayValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
byte a = 255;
byte b = 0;
double p;
for (int i = 0; i < bytes; i++)
{
if (a > grayValues[i])
{
a = grayValues[i];
}
if (b < grayValues[i])
{
b = grayValues[i];
}
}
p = 255.0 / (b - a);
for (int i = 0; i < bytes; i++)
{
grayValues[i] = (byte)(p * (grayValues[i] - a) + 0.5);
}
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
curbitmap.UnlockBits(bmpdata);
Invalidate();
}
}
private void button7_Click(object sender, EventArgs e)
{
if (curbitmap != null)
{
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 = 3 * curbitmap.Width * curbitmap.Height;
byte[] grayValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
for (int i = 0; i < bytes; i += 3)
{
grayValues[i] = 0;
grayValues[i + 1] = 0;
}
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
curbitmap.UnlockBits(bmpdata);
Invalidate();
}
}
private void button8_Click(object sender, EventArgs e)
{
if (curbitmap != null)
{
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 = 3 * curbitmap.Width * curbitmap.Height;
byte[] grayValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
double[] junzhi = new double[3];
junzhi[0] = 0; junzhi[1] = 0; junzhi[2] = 0;
//double j = 0;
for (int i = 0; i < bytes; i += 3)
{
junzhi[0] += grayValues[i];
junzhi[1] += grayValues[i + 1];
junzhi[2] += grayValues[i + 2];
// grayValues[i + 1] = 0;
}
junzhi[0] = junzhi[0] / bytes * 3;
junzhi[1] = junzhi[1] / bytes * 3;
junzhi[2] = junzhi[2] / bytes * 3;
double[] var = new double[3];
var[0] = 0; var[1] = 0; var[2] = 0;
for (int i = 0; i < bytes; i += 3)
{
var[0] += (grayValues[i] - junzhi[0]) * (grayValues[i] - junzhi[0]);
var[1] += (grayValues[i + 1] - junzhi[1]) * (grayValues[i + 1] - junzhi[1]);
var[2] += (grayValues[i + 2] - junzhi[2]) * (grayValues[i + 2] - junzhi[2]);
// grayValues[i + 1] = 0;
}
var[0] = var[0] / bytes * 3;
var[1] = var[1] / bytes * 3;
var[2] = var[2] / bytes * 3;
for (int i = 0; i < bytes; i += 3)
{
if (grayValues[i] > junzhi[0])
{
grayValues[i] = (byte)(150 + Math.Sqrt(2000 * (grayValues[i] - junzhi[0]) / var[0]));
}
else
grayValues[i] = (byte)(150 - Math.Sqrt(2000 * (junzhi[0] - grayValues[i]) / var[0]));
if (grayValues[i + 1] > junzhi[1])
{
grayValues[i + 1] = (byte)(150 + Math.Sqrt(2000 * (grayValues[i + 1] - junzhi[1]) / var[1]));
}
else
grayValues[i + 1] = (byte)(150 - Math.Sqrt(2000 * (junzhi[1] - grayValues[i + 1]) / var[1]));
if (grayValues[i + 2] > junzhi[2])
{
grayValues[i + 2] = (byte)(150 + Math.Sqrt(2000 * (grayValues[i + 2] - junzhi[2]) / var[2]));
}
else
grayValues[i + 2] = (byte)(150 - Math.Sqrt(2000 * (junzhi[2] - grayValues[i + 2]) / var[2]));
}
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
curbitmap.UnlockBits(bmpdata);
Invalidate();
}
}
Bitmap beijingmap;
private void button9_Click(object sender, EventArgs e)
{
if (curbitmap != null)
{
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 = bmpdata.Stride * bmpdata.Height;
byte[] grayValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
//double colortemp = 0;
int M = 3;
int H = curbitmap.Height / 3;
int L = curbitmap.Width / 3;
double[,] av = new double[H, L];
double[,] var = new double[H, L];
double sav = 0;
double svar = 0;
//计算每一块的平均值
for (int x = 1; x < H; x += 1)
{
for (int y = 1; y < L; y += 1)
{
for (int i = 0; i < M; i++)
{
for (int j = 0; j < M; j++)
{
int X = i + (x - 1) * M;
int Y = j + (y - 1) * M;
sav += grayValues[X * bmpdata.Stride + Y * 3];
}
}
av[x, y] = sav / 9;
sav = 0;
for (int i = 0; i < M; i++)
{
for (int j = 0; j < M; j++)
{
int X = i + (x - 1) * M;
int Y = j + (y - 1) * M;
svar += (grayValues[X * bmpdata.Stride + Y * 3] - av[x, y]) * (grayValues[X * bmpdata.Stride + Y * 3] - av[x, y]);
}
}
var[x, y] = svar / 9;
svar = 0;
}
}
//所有块的平均值和方差
double Gmean = 0;
double Vmean = 0;
for (int i = 0; i < H; i++)
{
for (int j = 0; j < L; j++)
{
Gmean = Gmean + av[i, j];
Vmean += var[i, j];
}
}
double Gmean1 = Gmean / (H * L);
double Vmean1 = Vmean / (H * L);
double gtemp = 0;
double gtotle = 0;
double vtemp = 0;
double vtotle = 0;
for (int x = 0; x < H; x++)
{
for (int y = 0; y < L; y++)
{
if (Gmean1 > av[x, y])
{
gtemp += 1;
gtotle += av[x, y];
}
if (Vmean1 < var[x, y])
{
vtemp += 1;
vtotle += var[x, y];
}
}
}
double G1 = gtotle / gtemp;
double V1 = vtotle / vtemp;
double gtemp1 = 0;
double gtotle1 = 0;
double vtemp1 = 0;
double vtotle1 = 0;
for (int x = 0; x < H; x++)
{
for (int y = 0; y < L; y++)
{
if (G1 > av[x, y])
{
gtemp1 += 1;
gtotle1 += av[x, y];
}
if (0 < var[x, y] && var[x, y] < V1)
{
vtemp1 += 1;
vtotle1 += var[x, y];
}
}
}
double G2 = gtotle1 / gtemp1;
double V2 = vtotle1 / vtemp1;
//构建矩阵
double[,] E = new double[H, L];
for (int x = 0; x < H; x++)
{
for (int y = 0; y < L; y++)
{
if (av[x, y] > G2 && var[x, y] < V2)
{
E[x, y] = 1;
}
if (av[x, y] < (G1 - 130) && var[x, y] < V2)
{
E[x, y] = 1;
}
}
}
for (int x = 1; x < H - 1; x++)
{
for (int y = 1; y < L - 1; y++)
{
if (E[x, y] == 1)
{
if (E[x - 1, y] + E[x, y + 1] + E[x + 1, y + 1] + E[x - 1, y + 1] + E[x + 1, y] + E[x + 1, y - 1]
+ E[x, y - 1] + E[x - 1, y - 1] <= 4)
{
E[x, y] = 0;
}
}
}
}
beijingmap = new Bitmap(curbitmap.Width, curbitmap.Height);
for (int i = 0; i < beijingmap.Width; i++)
{
for (int j = 0; j < beijingmap.Height; j++)
{
beijingmap.SetPixel(i, j, Color.FromArgb(255, 255, 255));
}
}
for (int x = 1; x < H; x++)
{
for (int y = 1; y < L; y++)
{
if (E[x, y] == 1)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
int X = i + (x - 1) * M;
int Y = j + (y - 1) * M;
grayValues[X * bmpdata.Stride + Y * 3] = (byte)G1;
grayValues[X * bmpdata.Stride + Y * 3 + 1] = (byte)G1;
grayValues[X * bmpdata.Stride + Y * 3 + 2] = (byte)G1;
beijingmap.SetPixel(Y, X, Color.FromArgb(1, 1, 1));
}
}
}
}
}
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
curbitmap.UnlockBits(bmpdata);
Invalidate();
beijingtu map = new beijingtu(beijingmap);
map.Show();
}
}
private void button2_Click(object sender, EventArgs e)
{
Graphics g = this.panel1.CreateGraphics();
g.Clear(panel1.BackColor);
curbitmap = null;
g.Dispose();
}
private void button10_Click(object sender, EventArgs e)
{
if (curbitmap != null)
{
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 = bmpdata.Stride * bmpdata.Height;
byte[] grayValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
double colortemp = 0;
for (int i = 0; i < bmpdata.Height; i += 1)
{
for (int j = 0; j < bmpdata.Width; j += 1)
{
colortemp = grayValues[i * bmpdata.Stride + 3 * j + 2] * 0.299 + grayValues[i * bmpdata.Stride + 3 * j + 1] * 0.587 +
grayValues[i * bmpdata.Stride + 3 * j] * 0.114;
grayValues[i * bmpdata.Stride + 3 * j + 2] = grayValues[i * bmpdata.Stride + 3 * j + 1] = grayValues[i * bmpdata.Stride + 3 * j]
= (byte)colortemp;
}
}
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
curbitmap.UnlockBits(bmpdata);
Invalidate();
}
}
private void button11_Click(object sender, EventArgs e)
{
if (curbitmap != null)
{
Convolution c = new Convolution();
curbitmap = c.Smooth(curbitmap);
}
}
private void button12_Click(object sender, EventArgs e)
{
if (curbitmap != null)
{
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 = bmpdata.Stride * bmpdata.Height;
byte[] grayValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
double[,] Gx = new double[bmpdata.Stride, curbitmap.Height];
double[,] Gy = new double[bmpdata.Stride, curbitmap.Height];
double[,] G = new double[bmpdata.Stride, curbitmap.Height];
double colortemp = 0;
for (int i = 1; i < bmpdata.Height - 1; i += 1)
{
for (int j = 1; j < bmpdata.Width - 2; j += 1)
{
Gx[i, j] = (-1) * (grayValues[(i - 1) * bmpdata.Stride + 3 * (j - 1) + 2] + grayValues[(i - 1) * bmpdata.Stride + 3 * (j - 1) + 1] +
grayValues[(i - 1) * bmpdata.Stride + 3 * (j - 1)]) +
(1) * (grayValues[(i + 1) * bmpdata.Stride + 3 * (j - 1) + 2] + grayValues[(i + 1) * bmpdata.Stride + 3 * (j - 1) + 1] +
grayValues[(i + 1) * bmpdata.Stride + 3 * (j - 1)]) +
(-2) * (grayValues[(i - 1) * bmpdata.Stride + 3 * (j) + 2] + grayValues[(i - 1) * bmpdata.Stride + 3 * (j) + 1] +
grayValues[(i - 1) * bmpdata.Stride + 3 * (j)]) +
(2) * (grayValues[(i + 1) * bmpdata.Stride + 3 * (j) + 2] + grayValues[(i + 1) * bmpdata.Stride + 3 * (j) + 1] +
grayValues[(i + 1) * bmpdata.Stride + 3 * (j)]) +
(-1) * (grayValues[(i - 1) * bmpdata.Stride + 3 * (j + 1) + 2] + grayValues[(i - 1) * bmpdata.Stride + 3 * (j + 1) + 1] +
grayValues[(i - 1) * bmpdata.Stride + 3 * (j + 1)]) +
(1) * (grayValues[(i + 1) * bmpdata.Stride + 3 * (j + 1) + 2] + grayValues[(i + 1) * bmpdata.Stride + 3 * (j + 1) + 1] +
grayValues[(i + 1) * bmpdata.Stride + 3 * (j + 1)]);
Gy[i, j] = (1) * (grayValues[(i - 1) * bmpdata.Stride + 3 * (j - 1) + 2] + grayValues[(i - 1) * bmpdata.Stride + 3 * (j - 1) + 1] +
grayValues[(i - 1) * bmpdata.Stride + 3 * (j - 1)]) +
(2) * (grayValues[(i) * bmpdata.Stride + 3 * (j - 1) + 2] + grayValues[(i) * bmpdata.Stride + 3 * (j - 1) + 1] +
grayValues[(i) * bmpdata.Stride + 3 * (j - 1)]) +
(1) * (grayValues[(i + 1) * bmpdata.Stride + 3 * (j - 1) + 2] + grayValues[(i + 1) * bmpdata.Stride + 3 * (j - 1) + 1] +
grayValues[(i + 1) * bmpdata.Stride + 3 * (j - 1)]) +
0 * (grayValues[(i - 1) * bmpdata.Stride + 3 * (j) + 2] + grayValues[(i - 1) * bmpdata.Stride + 3 * (j) + 1] +
grayValues[(i - 1) * bmpdata.Stride + 3 * (j)]) +
0 * (grayValues[(i + 1) * bmpdata.Stride + 3 * (j) + 2] + grayValues[(i + 1) * bmpdata.Stride + 3 * (j) + 1] +
grayValues[(i + 1) * bmpdata.Stride + 3 * (j)]) +
(-1) * (grayValues[(i - 1) * bmpdata.Stride + 3 * (j + 1) + 2] + grayValues[(i - 1) * bmpdata.Stride + 3 * (j + 1) + 1] +
grayValues[(i - 1) * bmpdata.Stride + 3 * (j + 1)]) +
(-1) * (grayValues[(i + 1) * bmpdata.Stride + 3 * (j + 1) + 2] + grayValues[(i + 1) * bmpdata.Stride + 3 * (j + 1) + 1] +
grayValues[(i + 1) * bmpdata.Stride + 3 * (j + 1)]) +
(-2) * (grayValues[(i) * bmpdata.Stride + 3 * (j + 1) + 2] + grayValues[(i) * bmpdata.Stride + 3 * (j + 1) + 1] +
grayValues[(i) * bmpdata.Stride + 3 * (j + 1)]);
G[i,j] = Math.Atan2(Gy[i, j],Gx[i, j]);
grayValues[(i) * bmpdata.Stride + 3 * (j) ] = (byte)G[i,j];
grayValues[(i) * bmpdata.Stride + 3 * (j) + 1] = (byte)G[i, j];
grayValues[(i) * bmpdata.Stride + 3 * (j) + 2] = (byte)G[i, j];
;
}
}
double g = 0;double gy = 0;
//for (int i = 1; i < bmpdata.Height - 1; i += 1)
//{
// for (int j = 1; j < bmpdata.Width - 2; j += 1)
// {
// g += G[i, j];
// }
//}
double jx = g / (bmpdata.Height - 1)/ (bmpdata.Width - 2);
//double jy = gy / (bmpdata.Width - 2);
for (int i = 1; i < bmpdata.Height - 1; i += 1)
{
for (int j = 1; j < bmpdata.Width - 2; j += 1)
{
grayValues[(i) * bmpdata.Stride + 3 * (j)] = (byte)255;
grayValues[(i) * bmpdata.Stride + 3 * (j) + 1] = (byte)255;
grayValues[(i) * bmpdata.Stride + 3 * (j) + 2] = (byte)255;
if (G[i, j] <1)
{
grayValues[(i) * bmpdata.Stride + 3 * (j)] = (byte)0;
grayValues[(i) * bmpdata.Stride + 3 * (j) + 1] = (byte)0;
grayValues[(i) * bmpdata.Stride + 3 * (j) + 2] = (byte)0;
}
}
}
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
curbitmap.UnlockBits(bmpdata);
Invalidate();
}
}
private void Image_Test()
{
if (this.curbitmap != null)
{
int Height = curbitmap.Height;
int Width = curbitmap.Width;
Bitmap bitmap = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
Bitmap MyBitmap = curbitmap;
BitmapData oldData = MyBitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); //原图
BitmapData newData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); //新图即边缘图
unsafe
{
//首先第一段代码是提取边缘,边缘置为黑色,其他部分置为白色
byte* pin_1 = (byte*)(oldData.Scan0.ToPointer());
byte* pin_2 = pin_1 + (oldData.Stride);
byte* pout = (byte*)(newData.Scan0.ToPointer());
double[,] R = new double[oldData.Height - 1, oldData.Width];
for (int y = 0; y < oldData.Height - 1; y++)
{
for (int x = 0; x < oldData.Width; x++)
{
//使用robert算子
double b = System.Math.Sqrt(((double)pin_1[0] - (double)(pin_2[0] + 3)) * ((double)pin_1[0] - (double)(pin_2[0] + 3)) + ((double)(pin_1[0] + 3) - (double)pin_2[0]) * ((double)(pin_1[0] + 3) - (double)pin_2[0]));
double g = System.Math.Sqrt(((double)pin_1[1] - (double)(pin_2[1] + 3)) * ((double)pin_1[1] - (double)(pin_2[1] + 3)) + ((double)(pin_1[1] + 3) - (double)pin_2[1]) * ((double)(pin_1[1] + 3) - (double)pin_2[1]));
double r = System.Math.Sqrt(((double)pin_1[2] - (double)(pin_2[2] + 3)) * ((double)pin_1[2] - (double)(pin_2[2] + 3)) + ((double)(pin_1[2] + 3) - (double)pin_2[2]) * ((double)(pin_1[2] + 3) - (double)pin_2[2]));
double bgr = b + g + r;//博主一直在纠结要不要除以3,感觉没差,选阈值的时候调整一下就好了- -
if (bgr > 80) //阈值,超过阈值判定为边缘(选取适当的阈值)
{
b = 0;
g = 0;
r = 0;
}
else
{
b = 255;
g = 255;
r = 255;
}
pout[0] = (byte)(b);
pout[1] = (byte)(g);
pout[2] = (byte)(r);
pin_1 = pin_1 + 3;
pin_2 = pin_2 + 3;
pout = pout + 3;
}
pin_1 += oldData.Stride - oldData.Width * 3;
pin_2 += oldData.Stride - oldData.Width * 3;
pout += newData.Stride - newData.Width * 3;
}
bitmap.UnlockBits(newData);
MyBitmap.UnlockBits(oldData);
this.curbitmap = bitmap;
}
}
}
private void button13_Click(object sender, EventArgs e)
{
Image_Test();
}
private void button14_Click(object sender, EventArgs e)
{
curbitmap = ToThinner(curbitmap);
}
public unsafe Bitmap ToThinner(Bitmap srcImg)
{
int iw = srcImg.Width;
int ih = srcImg.Height;
bool bModified; //二值图像修改标志
bool bCondition1; //细化条件1标志
bool bCondition2; //细化条件2标志
bool bCondition3; //细化条件3标志
bool bCondition4; //细化条件4标志
int nCount;
//5X5像素块
byte[,] neighbour = new byte[5, 5];
//新建临时存储图像
Bitmap NImg = new Bitmap(iw, ih, srcImg.PixelFormat);
bModified = true;
//细化修改标志, 用作循环条件
BitmapData dstData = srcImg.LockBits(new Rectangle(0, 0, iw, ih), ImageLockMode.ReadWrite, srcImg.PixelFormat);
byte* data = (byte*)(dstData.Scan0);
//将图像转换为0,1二值得图像;
int step = dstData.Stride;
for (int i = 0; i < dstData.Height; i++)
{
for (int j = 0; j < dstData.Width * 3; j += 3)
{
if (data[i * step + j] > 128)
//如果是白线条,只要将0改成1,将1改成0
data[i * step + j]
= data[i * step + j + 1]
= data[i * step + j + 2]
= 0;
else
data[i * step + j]
= data[i * step + j + 1]
= data[i * step + j + 2]
= 1;
}
}
BitmapData dstData1 = NImg.LockBits(new Rectangle(0, 0, iw, ih), ImageLockMode.ReadWrite, NImg.PixelFormat);
byte* data1 = (byte*)(dstData1.Scan0);
int step1 = dstData1.Stride;
//细化循环开始
while (bModified)
{
bModified = false;
//初始化临时二值图像NImg
for (int i = 0; i < dstData1.Height; i++)
{
for (int j = 0; j < dstData1.Width * 3; j++)
{
data1[i * step1 + j] = 0;
}
}
for (int i = 2; i < ih - 2; i++)
{
for (int j = 6; j < iw * 3 - 6; j += 3)
{
bCondition1 = false;
bCondition2 = false;
bCondition3 = false;
bCondition4 = false;
if (data[i * step + j] == 0)
//若图像的当前点为白色,则跳过
continue;
for (int k = 0; k < 5; k++)
{
//取以当前点为中心的5X5块
for (int l = 0; l < 5; l++)
{
//1代表黑色, 0代表白色
//neighbour[k, l] = bw[i + k - 2, j + l - 2];
//neighbour[k, l] = data[(i + k - 2) * step + (j + l - 2)];
neighbour[k, l] = data[(i + k - 2) * step + (j + l * 3 - 6)];
}
}
//(1)判断条件2<=n(p)<=6
nCount = neighbour[1, 1] + neighbour[1, 2] + neighbour[1, 3] + neighbour[2, 1] + neighbour[2, 3] + neighbour[3, 1] + neighbour[3, 2] + neighbour[3, 3];
if (nCount >= 2 && nCount <= 6)
bCondition1 = true;
else
{
data1[i * step1 + j] = 1;
continue;
//跳过, 加快速度
}
//(2)判断s(p)=1
nCount = 0;
if (neighbour[2, 3] == 0 && neighbour[1, 3] == 1)
nCount++;
if (neighbour[1, 3] == 0 && neighbour[1, 2] == 1)
nCount++;
if (neighbour[1, 2] == 0 && neighbour[1, 1] == 1)
nCount++;
if (neighbour[1, 1] == 0 && neighbour[2, 1] == 1)
nCount++;
if (neighbour[2, 1] == 0 && neighbour[3, 1] == 1)
nCount++;
if (neighbour[3, 1] == 0 && neighbour[3, 2] == 1)
nCount++;
if (neighbour[3, 2] == 0 && neighbour[3, 3] == 1)
nCount++;
if (neighbour[3, 3] == 0 && neighbour[2, 3] == 1)
nCount++;
if (nCount == 1)
bCondition2 = true;
else
{
data1[i * step1 + j] = 1;
continue;
}
//(3)判断p0*p2*p4=0 or s(p2)!=1
if (neighbour[2, 3] * neighbour[1, 2] * neighbour[2, 1] == 0)
bCondition3 = true;
else
{
nCount = 0;
if (neighbour[0, 2] == 0 && neighbour[0, 1] == 1)
nCount++;
if (neighbour[0, 1] == 0 && neighbour[1, 1] == 1)
nCount++;
if (neighbour[1, 1] == 0 && neighbour[2, 1] == 1)
nCount++;
if (neighbour[2, 1] == 0 && neighbour[2, 2] == 1)
nCount++;
if (neighbour[2, 2] == 0 && neighbour[2, 3] == 1)
nCount++;
if (neighbour[2, 3] == 0 && neighbour[1, 3] == 1)
nCount++;
if (neighbour[1, 3] == 0 && neighbour[0, 3] == 1)
nCount++;
if (neighbour[0, 3] == 0 && neighbour[0, 2] == 1)
nCount++;
if (nCount != 1)
//s(p2)!=1
bCondition3 = true;
else
{
data1[i * step1 + j] = 1;
continue;
}
}
//(4)判断p2*p4*p6=0 or s(p4)!=1
if (neighbour[1, 2] * neighbour[2, 1] * neighbour[3, 2] == 0)
bCondition4 = true;
else
{
nCount = 0;
if (neighbour[1, 1] == 0 && neighbour[1, 0] == 1)
nCount++;
if (neighbour[1, 0] == 0 && neighbour[2, 0] == 1)
nCount++;
if (neighbour[2, 0] == 0 && neighbour[3, 0] == 1)
nCount++;
if (neighbour[3, 0] == 0 && neighbour[3, 1] == 1)
nCount++;
if (neighbour[3, 1] == 0 && neighbour[3, 2] == 1)
nCount++;
if (neighbour[3, 2] == 0 && neighbour[2, 2] == 1)
nCount++;
if (neighbour[2, 2] == 0 && neighbour[1, 2] == 1)
nCount++;
if (neighbour[1, 2] == 0 && neighbour[1, 1] == 1)
nCount++;
if (nCount != 1)//s(p4)!=1
bCondition4 = true;
}
if (bCondition1 && bCondition2 && bCondition3 && bCondition4)
{
data1[i * step1 + j] = 0;
bModified = true;
}
else
{
data1[i * step1 + j] = 1;
}
}
}
// 将细化了的临时图像bw_tem[w,h]copy到bw[w,h],完成一次细化
for (int i = 2; i < ih - 2; i++)
for (int j = 2; j < iw * 3 - 2; j++)
data[i * step + j] = data1[i * step1 + j];
}
for (int i = 2; i < ih - 2; i++)
{
for (int j = 6; j < iw * 3 - 6; j += 3)
{
if (data[i * step + j] == 1)
data[i * step + j]
= data[i * step + j + 1]
= data[i * step + j + 2]
= 0;
else
data[i * step + j]
= data[i * step + j + 1]
= data[i * step + j + 2]
= 255;
}
}
srcImg.UnlockBits(dstData);
NImg.UnlockBits(dstData1);
return (srcImg);
}
private void button15_Click(object sender, EventArgs e)
{
Convolution c = new Convolution();
this.curbitmap = c.kaiyunsuan(curbitmap);
}
private void button16_Click(object sender, EventArgs e)
{
Convolution c = new Convolution();
this.curbitmap = c.expend(curbitmap);
}
private void button17_Click(object sender, EventArgs e)
{
Moravec m = new Moravec(curbitmap);
m.Show();
}
}
}
moravec.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace shuzituxiangchuli
{
public partial class Moravec : Form
{
public Bitmap curbitmap;
public Moravec(Bitmap map)
{
this.curbitmap = map;
InitializeComponent();
}
private void Moravec_Load(object sender, EventArgs e)
{
}
private void pictureBox1_Click(object sender, EventArgs e)
{
Graphics g = this.pictureBox1.CreateGraphics();
int x, y;
x = curbitmap.Width / 3;
y = curbitmap.Height / 3;
//while (x > this.pictureBox1.Width && y > this.pictureBox1.Height )
//{
// x = x / 2;
// y = y / 2;
//}
g.DrawImage(curbitmap, 0, 0, x, y);
}
public double[,] gethuiduzhi(Bitmap map)
{
double[,] huiduzhi = new double[map.Width, map.Height];
int w = map.Width;
int h = map.Height;
for (int i = 0; i < w; i++)
{
for (int j = 0; j < h; j++)
{
Color c = map.GetPixel(i, j);
huiduzhi[i, j] = c.R * 0.299 + c.G * 0.587 + c.B * 0.114;
}
}
return huiduzhi;
}
private void button1_Click(object sender, EventArgs e)
{
if (curbitmap != null)
{
progressBar1.Visible = true;
progressBar1.Maximum = 7;
progressBar1.Value = 0;
progressBar1.Step = 1;
double[,] huidu = new double[this.curbitmap.Width, this.curbitmap.Height];
huidu = gethuiduzhi(curbitmap);
progressBar1.Value += progressBar1.Step;
int w = curbitmap.Width;
int h = curbitmap.Height;
double[,] xingquzhi = new double[w,h];
for (int i = 2; i < w - 2; i++)
{
for (int j = 2; j < h - 2; j++)
{
double V1 = 0;
for (int m = 0; m < 4; m++)
{
V1 += Math.Pow(huidu[i - 2 + m, j] - huidu[i - 1 + m, j], 2);
}
double V2 = 0;
for (int m = 0; m < 4; m++)
{
V2 += Math.Pow(huidu[i - 2 + m, j - 2 + m] - huidu[i - 1 + m, j - 1 + m], 2);
}
double V3 = 0;
for (int m = 0; m < 4; m++)
{
V3 += Math.Pow(huidu[i, j - 2 + m] - huidu[i, j - 1 + m], 2);
}
double V4 = 0;
for (int m = 0; m < 4; m++)
{
V4 += Math.Pow(huidu[i - 2 + m, j + 2 - m] - huidu[i - 1 + m, j + 1 - m], 2);
}
xingquzhi[i, j] = Math.Min(Math.Min(Math.Min(V1, V2), V3), V4);
}
}
progressBar1.Value += progressBar1.Step;
double sum = 0;
for (int i = 0; i < w ; i++)
{
for (int j =0 ; j < h; j++)
{
sum += xingquzhi[i, j];
}
}
double pingjun = sum / ((w) * (h ));
progressBar1.Value += progressBar1.Step;
int houxuan = 0;
int c = 10001;
double zeng = 1;
int[,] tezhengzhi = new int[houxuan, 2];
while (c>10000)
{
c = 0;
double yuzhi = pingjun * zeng;
double[,] jianding = new double[w, h];
for (int i=2;i<w-2;i++)
{
for (int j=2;j<h-2;j++)
{
if(xingquzhi[i,j]<=yuzhi)
{
jianding[i, j] = 0;
}
else
{
jianding[i, j] = 1;
houxuan++;
}
}
}
int [,]tezhengzhi1 = new int[houxuan, 2];
int yuzhimuban = 5;
int mubanbanchaung = 2;
for(int i=mubanbanchaung;i<w-mubanbanchaung;i=i+1)
{
for(int j=mubanbanchaung;j<h-mubanbanchaung;j++)
{
double MAX = 0;
int a = 0;
int b = 0;
for(int m=0;m<yuzhimuban;m++)
{
for (int n=0;n<yuzhimuban;n++)
{
if(jianding[i-mubanbanchaung+m,j-mubanbanchaung+n]==1)
{
if(MAX<xingquzhi[i-mubanbanchaung+m,j-mubanbanchaung+n])
{
MAX = xingquzhi[i - mubanbanchaung + m, j - mubanbanchaung + n];
a = i - mubanbanchaung + m;
b = j - mubanbanchaung + n;
}
}
else
{
a = 0;b = 0;
}
}
}
if((a!=0)&&(b!=0)&&jianding[i,j]==1)
{
tezhengzhi1[c, 0] = a;
tezhengzhi1[c, 1] = b;
c++;
}
}
}
tezhengzhi = tezhengzhi1;
zeng=zeng+1;
}
progressBar1.Value += progressBar1.Step;
progressBar1.Value += progressBar1.Step;
int[,] tezhengzhi2 = new int[c,2];
tezhengzhi2 = tezhengzhi;
Graphics g = this.pictureBox2.CreateGraphics();
int x, y;
x = curbitmap.Width/3;
y = curbitmap.Height/3;
//while (x > this.pictureBox1.Width && y > this.pictureBox1.Height)
//{
// x = x / 2;
// y = y / 2;
//}
g.DrawImage(curbitmap, 0, 0, x, y);
progressBar1.Value += progressBar1.Step;
Pen p = new Pen(Color.Red);
for(int i=0;i<c;i++)
{
x = tezhengzhi2[i, 0]/3;
y = tezhengzhi2[i, 1]/3;
g.DrawLine(p, x - 5, y, x + 5, y);
g.DrawLine(p, x , y-5, x , y+5);
}
progressBar1.Value += progressBar1.Step;
// progressBar1.Visible = false;
g.Dispose();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
}
}
}
全部评论 (0)
还没有任何评论哟~
