图像二值化和显示3D 的算法实现

首先根据图片进行裁剪  得到有用的数据

  1   public static int[,] RGB2Gray(Bitmap srcBitmap)
  2         {
  3 
  4             int wide = srcBitmap.Width;
  5 
  6             int height = srcBitmap.Height;
  7 
  8             Rectangle rect = new Rectangle(0, 0, wide, height);
  9 
 10             // 将Bitmap锁定到系统内存中, 获得BitmapData
 11 
 12             BitmapData srcBmData = srcBitmap.LockBits(rect,
 13 
 14                       ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
 15 
 16             //创建Bitmap
 17 
 18             Bitmap dstBitmap = CreateGrayscaleImage(wide, height);//这个函数在后面有定义
 19 
 20             BitmapData dstBmData = dstBitmap.LockBits(rect,
 21 
 22             ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
 23 
 24             // 位图中第一个像素数据的地址。它也可以看成是位图中的第一个扫描行
 25 
 26             System.IntPtr srcPtr = srcBmData.Scan0;
 27 
 28             System.IntPtr dstPtr = dstBmData.Scan0;
 29 
 30             // 将Bitmap对象的信息存放到byte数组中
 31 
 32             int src_bytes = srcBmData.Stride * height;
 33 
 34             byte[] srcValues = new byte[src_bytes];
 35 
 36             int dst_bytes = dstBmData.Stride * height;
 37 
 38             byte[] dstValues = new byte[dst_bytes];
 39 
 40             //复制GRB信息到byte数组
 41 
 42             System.Runtime.InteropServices.Marshal.Copy(srcPtr, srcValues, 0, src_bytes);
 43 
 44             System.Runtime.InteropServices.Marshal.Copy(dstPtr, dstValues, 0, dst_bytes);
 45 
 46             int unm = 365;
 47             // 根据Y=0.299*R+0.114*G+0.587B,Y为亮度
 48             int[,] imgData = new int[wide, height - 365 - 37];
 49 
 50             for (int i = 365; i < height - 37; i++)
 51 
 52                 for (int j = 0; j < wide; j++)
 53 
 54                 {
 55 
 56                     //只处理每行中图像像素数据,舍弃未用空间
 57 
 58                     //注意位图结构中RGB按BGR的顺序存储
 59 
 60                     int k = 3 * j;
 61 
 62                     double temp = srcValues[i * srcBmData.Stride + k + 1];// (double)(srcValues[i * srcBmData.Stride + k + 2] * .299
 63 
 64                     //+ srcValues[i * srcBmData.Stride + k + 1] * .587 + srcValues[i * srcBmData.Stride + k] * .114);
 65 
 66                     dstValues[i * dstBmData.Stride + j] = (byte)temp;
 67                     //imgData[j,i,0] = srcValues[i * srcBmData.Stride + k + 2];
 68                     imgData[j, i - 365] = srcValues[i * srcBmData.Stride + k + 1];
 69                     //imgData[j, i, 2] = srcValues[i * srcBmData.Stride + k ];
 70                 }
 71 
 72             //将更改过的byte[]拷贝到原位图
 73 
 74             System.Runtime.InteropServices.Marshal.Copy(dstValues, 0, dstPtr, dst_bytes);
 75 
 76 
 77 
 78             // 解锁位图
 79 
 80             srcBitmap.UnlockBits(srcBmData);
 81 
 82             dstBitmap.UnlockBits(dstBmData);
 83             dstBitmap.Save("1.jpg");
 84             return imgData;
 85 
 86 
 87 
 88         }//#
 89         public static Bitmap CreateGrayscaleImage(int width, int height)
 90 
 91         {
 92 
 93             // create new image
 94 
 95             Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
 96 
 97             // set palette to grayscale
 98 
 99             // check pixel format
100 
101             if (bmp.PixelFormat != PixelFormat.Format8bppIndexed)
102 
103                 throw new ArgumentException();
104 
105 
106 
107             // get palette
108 
109             ColorPalette cp = bmp.Palette;
110 
111             // init palette
112 
113             for (int i = 0; i < 256; i++)
114 
115             {
116 
117                 cp.Entries[i] = Color.FromArgb(i, i, i);
118 
119             }
120 
121             // set palette back
122 
123             bmp.Palette = cp;
124 
125             // return new image
126 
127             return bmp;
128 
129         }//#
130     
View Code

然后对其进行调用

 1         private void setImgData()
 2         {
 3             try
 4             {
 5                 Bitmap img = new Bitmap(imgname);
 6                 int wide = img.Width;
 7                 int height = img.Height - 365 - 37;
 8 
 9                 var data1 = RGB2Gray(img);
10                 var val = CalcRec.GetLimetImage(data1, valColor, valContinuou); //返回缺陷级别
11                 string isokstr = "正常";
12                 switch (val)
13                 {
14                     case 0:
15                         isokstr = "正常";
16                         break;
17                     case 1:
18                         isokstr = "裂纹";
19                         break;
20                     case 2:
21                         isokstr = "焊缝";
22                         break;
23                     default:
24                         isokstr = "未知";
25                         break;
26                 }
27                 label_res.Text = isokstr;
28                 int ii = 0;
29 
30                 for (int i = 0; i < wide; i++)
31                 {
32 
33                     for (int j = 0; j < height; j++)
34                     {
35                         uint setColor = 0;
36                         if (data1[i, j] == 0)
37                         {
38                             setColor = (uint)ColorTranslator.ToOle(Color.FromArgb(0, 0, 200));
39                         }
40                         else
41                         {
42                             int color = PraseColor((data1[i, j]));
43                             setColor = (uint)ColorTranslator.ToOle(Color.FromArgb(color, color, 0));// PraseColor(data1[i, j]);
44                         }
45                         axTChart9.Series(0).asSurface.AddXYZ(i, data1[i, j], j, "", setColor); //向Tower序列中添加数据
46                     }
47                     ii++;
48                     if (ii > 1000)
49                     {
50                         ii = 0;
51                         Application.DoEvents();
52                     }
53                 }
54 
55 
56             }
57             catch (Exception pe)
58             {
59 
60                 throw pe;
61             }
62         }
63 
64         private int PraseColor(int v)
65         {
66             int input_start = valColor; //最低数量范围的输入。
67             int input_end = 255; //最低数量范围的输入。
68             int out_start = 10; //编号最小的范围内输出。
69             int out_end = 255; //范围输出中人数最多的。INT输入= 127; //输入值。
70             int res = 0;
71             if (v > 0)
72             {
73                 res = (out_start + ((out_end - out_start) / (input_end - input_start)) * (v - input_start));
74             }
75 
76             return res;
77         }
78         private float PraseColor(double v, int inputEnd)
79         {
80             float input_start = 0; //最低数量范围的输入。
81             float input_end = 5000f; //最低数量范围的输入。
82             float out_start = 0f; //编号最小的范围内输出。
83             float out_end = 255f; //范围输出中人数最多的。INT输入= 127; //输入值。
84             float res = 0;
85             if (v > 1000)
86             {
87                 res = (out_start + ((out_end - out_start) / (input_end - input_start)) * ((int)v - input_start));
88             }
89 
90             return res;
91         }
92       
View Code

其中关键是 这个方法 对数据进行处理 GetLimetImage  对图像的相关 R G B  中的一层进行 判断

这个方法的逻辑是

   

 1        public static int GetLimetImage(int[,] imageGreen, int a1, int a2)
 2         {
 3             List<int> coumindex = new List<int>();
 4             HashSet<int> y = new HashSet<int>();
 5             for (int i = 0; i < imageGreen.GetLength(0); i++)
 6             {
 7                 int gcontiu = 0;
 8                 int contiu = 0;
 9                 for (int j = 0; j < imageGreen.GetLength(1); j++)
10                 {
11                     imageGreen[i, j] = -imageGreen[i, j] + 255;
12                     if (imageGreen[i, j] < a1)
13                     {
14                         imageGreen[i, j] = 0;
15                     }
16                     else
17                     {
18                         contiu++;
19                         if (contiu == a2)
20                         {
21                             gcontiu++;
22 
23                         }
24                     }
25                 }
26                 if (gcontiu == 0)
27                 {
28                     for (int k = 0; k < imageGreen.GetLength(1); k++)
29                     {
30                         imageGreen[i, k] = 0;
31                     }
32                 }
33                 else
34                 {
35                     coumindex.Add(i);
36                     for (int j = 0; j < imageGreen.GetLength(1); j++)
37                     {
38                         if (imageGreen[i, j] != 0)
39                         {
40                             y.Add(j);
41                         }
42                     }
43                 }
44             }
45             int p = coumindex.Count >0?1:0;
46             for (int i = 0; i < coumindex.Count - 1; i++)
47             {
48                 if (coumindex[i + 1] - coumindex[i] != 1)
49                 {
50                     p++;
51                 }
52             }
53     
54             var Val = 0;
55             if (coumindex.Count == 0|| y.Count==0) {
56                 return Val;
57             }
58             if (p == 1) {
59                 Val = 1;
60             } else {
61                 long allpoint = 0;
62                 int[,] allpointDel = new int[coumindex.Count, y.Count];
63 
64                 for (int i = 0; i < coumindex.Count; i++)
65                 {
66                     for (int j = 0; j < y.Count; j++)
67                     {
68                         allpointDel[i, j] = imageGreen[coumindex[i], y.ElementAt(j)];
69                         allpoint = allpoint + imageGreen[coumindex[i], y.ElementAt(j)];
70                     }
71                 }
72                 var mevn = allpoint / (coumindex.Count * y.Count * 1.0);
73                 if (mevn < 40) {
74                     Val = 0;
75                 } else {
76                     Val = 2;
77                 }
78             }
79             return Val;
80         }
View Code

上图是MatLab 的mesh  下图是 TeeChar2017 

 直接调用的class

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Drawing;
  4 using System.Drawing.Imaging;
  5 using System.Linq;
  6 using System.Text;
  7 using System.Threading.Tasks;
  8 
  9 namespace ConsoleApplication1
 10 {
 11 
 12 
 13     public class CalcRec
 14     {
 15         static int valColor = 150;
 16         static int valContinuou = 15;
 17         static string imgname = "2.png";
 18 
 19         public static void setImgData()
 20         {
 21             try
 22             {
 23 
 24                 Bitmap img = new Bitmap(imgname);
 25                 int wide = img.Width;
 26                 int height = img.Height - 365 - 37;
 27 
 28                 var data1 = RGB2Gray(img);
 29                 var val = CalcRec.GetLimetImage(data1, valColor, valContinuou); //返回缺陷级别
 30                 string isokstr = "正常";
 31                 switch (val)
 32                 {
 33                     case 0:
 34                         isokstr = "正常";
 35                         break;
 36                     case 1:
 37                         isokstr = "裂纹";
 38                         break;
 39                     case 2:
 40                         isokstr = "焊缝";
 41                         break;
 42                     default:
 43                         isokstr = "未知";
 44                         break;
 45                 }
 46                 //label_res.Text = isokstr;
 47                 int ii = 0;
 48 
 49                 //for (int i = 0; i < wide; i++)
 50                 //{
 51 
 52                 //    for (int j = 0; j < height; j++)
 53                 //    {
 54                 //        uint setColor = 0;
 55                 //        if (data1[i, j] == 0)
 56                 //        {
 57                 //            setColor = (uint)ColorTranslator.ToOle(Color.FromArgb(0, 0, 200));
 58                 //        }
 59                 //        else
 60                 //        {
 61                 //            int color = PraseColor((data1[i, j]));
 62                 //            setColor = (uint)ColorTranslator.ToOle(Color.FromArgb(color, color, 0));// PraseColor(data1[i, j]);
 63                 //        }
 64                 //        axTChart9.Series(0).asSurface.AddXYZ(i, data1[i, j], j, "", setColor); //向Tower序列中添加数据
 65                 //    }
 66                 //    ii++;
 67                 //    if (ii > 1000)
 68                 //    {
 69                 //        ii = 0;
 70                 //        Application.DoEvents();
 71                 //    }
 72                 //}
 73 
 74 
 75             }
 76             catch (Exception pe)
 77             {
 78 
 79                 throw pe;
 80             }
 81         }
 82         public static int[,] RGB2Gray(Bitmap srcBitmap)
 83         {
 84 
 85             int wide = srcBitmap.Width;
 86 
 87             int height = srcBitmap.Height;
 88 
 89             Rectangle rect = new Rectangle(0, 0, wide, height);
 90 
 91             // 将Bitmap锁定到系统内存中, 获得BitmapData
 92 
 93             BitmapData srcBmData = srcBitmap.LockBits(rect,
 94 
 95                       ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
 96 
 97             //创建Bitmap
 98 
 99             Bitmap dstBitmap = CreateGrayscaleImage(wide, height);//这个函数在后面有定义
100 
101             BitmapData dstBmData = dstBitmap.LockBits(rect,
102 
103             ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
104 
105             // 位图中第一个像素数据的地址。它也可以看成是位图中的第一个扫描行
106 
107             System.IntPtr srcPtr = srcBmData.Scan0;
108 
109             System.IntPtr dstPtr = dstBmData.Scan0;
110 
111             // 将Bitmap对象的信息存放到byte数组中
112 
113             int src_bytes = srcBmData.Stride * height;
114 
115             byte[] srcValues = new byte[src_bytes];
116 
117             int dst_bytes = dstBmData.Stride * height;
118 
119             byte[] dstValues = new byte[dst_bytes];
120 
121             //复制GRB信息到byte数组
122 
123             System.Runtime.InteropServices.Marshal.Copy(srcPtr, srcValues, 0, src_bytes);
124 
125             System.Runtime.InteropServices.Marshal.Copy(dstPtr, dstValues, 0, dst_bytes);
126 
127             int unm = 365;
128             // 根据Y=0.299*R+0.114*G+0.587B,Y为亮度
129             int[,] imgData = new int[wide, height - 365 - 37];
130 
131             for (int i = 365; i < height - 37; i++)
132 
133                 for (int j = 0; j < wide; j++)
134 
135                 {
136 
137                     //只处理每行中图像像素数据,舍弃未用空间
138 
139                     //注意位图结构中RGB按BGR的顺序存储
140 
141                     int k = 3 * j;
142 
143                     double temp = srcValues[i * srcBmData.Stride + k + 1];// (double)(srcValues[i * srcBmData.Stride + k + 2] * .299
144 
145                     //+ srcValues[i * srcBmData.Stride + k + 1] * .587 + srcValues[i * srcBmData.Stride + k] * .114);
146 
147                     dstValues[i * dstBmData.Stride + j] = (byte)temp;
148                     //imgData[j,i,0] = srcValues[i * srcBmData.Stride + k + 2];
149                     imgData[j, i - 365] = srcValues[i * srcBmData.Stride + k + 1];
150                     //imgData[j, i, 2] = srcValues[i * srcBmData.Stride + k ];
151                 }
152 
153             //将更改过的byte[]拷贝到原位图
154 
155             System.Runtime.InteropServices.Marshal.Copy(dstValues, 0, dstPtr, dst_bytes);
156 
157 
158 
159             // 解锁位图
160 
161             srcBitmap.UnlockBits(srcBmData);
162 
163             dstBitmap.UnlockBits(dstBmData);
164             dstBitmap.Save("1.jpg");
165             return imgData;
166 
167 
168 
169         }//#
170         public static Bitmap CreateGrayscaleImage(int width, int height)
171 
172         {
173 
174             // create new image
175 
176             Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
177 
178             // set palette to grayscale
179 
180             // check pixel format
181 
182             if (bmp.PixelFormat != PixelFormat.Format8bppIndexed)
183 
184                 throw new ArgumentException();
185 
186 
187 
188             // get palette
189 
190             ColorPalette cp = bmp.Palette;
191 
192             // init palette
193 
194             for (int i = 0; i < 256; i++)
195 
196             {
197 
198                 cp.Entries[i] = Color.FromArgb(i, i, i);
199 
200             }
201 
202             // set palette back
203 
204             bmp.Palette = cp;
205 
206             // return new image
207 
208             return bmp;
209 
210         }//#
211         private int PraseColor(int v)
212         {
213             int input_start = valColor; //最低数量范围的输入。
214             int input_end = 255; //最低数量范围的输入。
215             int out_start = 10; //编号最小的范围内输出。
216             int out_end = 255; //范围输出中人数最多的。INT输入= 127; //输入值。
217             int res = 0;
218             if (v > 0)
219             {
220                 res = (out_start + ((out_end - out_start) / (input_end - input_start)) * (v - input_start));
221             }
222 
223             return res;
224         }
225         /// <summary>
226         /// 将图像的输入值映射到 别的范围
227         /// </summary>
228         /// <param name="v"></param>
229         /// <param name="inputEnd"></param>
230         /// <returns></returns>
231         private float PraseColor(double v, int inputEnd)
232         {
233             float input_start = 0; //最低数量范围的输入。
234             float input_end = 5000f; //最低数量范围的输入。
235             float out_start = 0f; //编号最小的范围内输出。
236             float out_end = 255f; //范围输出中人数最多的。INT输入= 127; //输入值。
237             float res = 0;
238             if (v > 1000)
239             {
240                 res = (out_start + ((out_end - out_start) / (input_end - input_start)) * ((int)v - input_start));
241             }
242 
243             return res;
244         }
245 
246 
247         public static int GetLimetImage(int[,] imageGreen, int a1, int a2)
248         {
249             List<int> coumindex = new List<int>();
250             HashSet<int> y = new HashSet<int>();
251             for (int i = 0; i < imageGreen.GetLength(0); i++)
252             {
253                 int gcontiu = 0;
254                 int contiu = 0;
255                 for (int j = 0; j < imageGreen.GetLength(1); j++)
256                 {
257                     imageGreen[i, j] = -imageGreen[i, j] + 255;
258                     if (imageGreen[i, j] < a1)
259                     {
260                         imageGreen[i, j] = 0;
261                     }
262                     else
263                     {
264                         contiu++;
265                         if (contiu == a2)
266                         {
267                             gcontiu++;
268 
269                         }
270                     }
271                 }
272                 if (gcontiu == 0)
273                 {
274                     for (int k = 0; k < imageGreen.GetLength(1); k++)
275                     {
276                         imageGreen[i, k] = 0;
277                     }
278                 }
279                 else
280                 {
281                     coumindex.Add(i);
282                     for (int j = 0; j < imageGreen.GetLength(1); j++)
283                     {
284                         if (imageGreen[i, j] != 0)
285                         {
286                             y.Add(j);
287                         }
288                     }
289                 }
290             }
291             int p = coumindex.Count >0?1:0;
292             for (int i = 0; i < coumindex.Count - 1; i++)
293             {
294                 if (coumindex[i + 1] - coumindex[i] != 1)
295                 {
296                     p++;
297                 }
298             }
299     
300             var Val = 0;
301             if (coumindex.Count == 0|| y.Count==0) {
302                 return Val;
303             }
304             if (p == 1) {
305                 Val = 1;
306             } else {
307                 long allpoint = 0;
308                 int[,] allpointDel = new int[coumindex.Count, y.Count];
309 
310                 for (int i = 0; i < coumindex.Count; i++)
311                 {
312                     for (int j = 0; j < y.Count; j++)
313                     {
314                         allpointDel[i, j] = imageGreen[coumindex[i], y.ElementAt(j)];
315                         allpoint = allpoint + imageGreen[coumindex[i], y.ElementAt(j)];
316                     }
317                 }
318                 var mevn = allpoint / (coumindex.Count * y.Count * 1.0);
319                 if (mevn < 40) {
320                     Val = 0;
321                 } else {
322                     Val = 2;
323                 }
324             }
325             return Val;
326         }
327 
328     }
329 }
View Code
 1         public static bool GetRGB(Bitmap Source, out int[,] R, out int[,] G, out int[,] B)
 2         {
 3             try
 4             {
 5                 int iWidth = Source.Width;
 6                 int iHeight = Source.Height;
 7                 Rectangle rect = new Rectangle(0, 0, iWidth, iHeight);
 8                 System.Drawing.Imaging.BitmapData bmpData = Source.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, Source.PixelFormat);
 9                 IntPtr iPtr = bmpData.Scan0;
10                 int iBytes = iWidth * iHeight * 3;
11                 byte[] PixelValues = new byte[iBytes];
12                 System.Runtime.InteropServices.Marshal.Copy(iPtr, PixelValues, 0, iBytes);
13                 Source.UnlockBits(bmpData);
14                 // 注意这个地方图像的两维方向与数组两维的方向是转置的关系
15                 R = new int[iHeight, iWidth];
16                 G = new int[iHeight, iWidth];
17                 B = new int[iHeight, iWidth];
18                 int iPoint = 0;
19                 for (int i = 0; i < iHeight; i++)
20                 {
21                     for (int j = 0; j < iWidth; j++)
22                     {
23                         // 注意,Windows 中三基色的排列顺序是 BGR 而不是 RGB!
24                         B[i, j] = Convert.ToInt32(PixelValues[iPoint++]);
25                         G[i, j] = Convert.ToInt32(PixelValues[iPoint++]);
26                         R[i, j] = Convert.ToInt32(PixelValues[iPoint++]);
27                     }
28                 }
29 
30                 return true;
31             }
32             catch (Exception)
33             {
34                 R = null;
35                 G = null;
36                 B = null;
37 
38                 return false;
39             }
40         }
41    
View Code
 1   public static int[,] RGB2Gray(Bitmap srcBitmap)
 2         {
 3             int wide = srcBitmap.Width;
 4             int height = srcBitmap.Height;
 5             Rectangle rect = new Rectangle(0, 0, wide, height);
 6             // 将Bitmap锁定到系统内存中, 获得BitmapData
 7             BitmapData srcBmData = srcBitmap.LockBits(rect,
 8                       ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
 9             //创建Bitmap
10             Bitmap dstBitmap = CreateGrayscaleImage(wide, height);//这个函数在后面有定义
11             BitmapData dstBmData = dstBitmap.LockBits(rect,
12             ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
13             // 位图中第一个像素数据的地址。它也可以看成是位图中的第一个扫描行
14             System.IntPtr srcPtr = srcBmData.Scan0;
15             System.IntPtr dstPtr = dstBmData.Scan0;
16             // 将Bitmap对象的信息存放到byte数组中
17             int src_bytes = srcBmData.Stride * height;
18             byte[] srcValues = new byte[src_bytes];
19             int dst_bytes = dstBmData.Stride * height;
20             byte[] dstValues = new byte[dst_bytes];
21             //复制GRB信息到byte数组
22             System.Runtime.InteropServices.Marshal.Copy(srcPtr, srcValues, 0, src_bytes);
23             System.Runtime.InteropServices.Marshal.Copy(dstPtr, dstValues, 0, dst_bytes);
24             int unm = 365;
25             // 根据Y=0.299*R+0.114*G+0.587B,Y为亮度
26             int[,] imgData = new int[wide, height - 365 - 37];
27             for (int i = 365; i < height - 37; i++)
28                 for (int j = 0; j < wide; j++)
29                 {
30                     //只处理每行中图像像素数据,舍弃未用空间
31                     //注意位图结构中RGB按BGR的顺序存储
32                     int k = 3 * j;
33                     double temp = srcValues[i * srcBmData.Stride + k + 1];
34                     dstValues[i * dstBmData.Stride + j] = (byte)temp;
35                     imgData[j, i - 365] = srcValues[i * srcBmData.Stride + k + 1];
36                 }
37             //将更改过的byte[]拷贝到原位图
38             System.Runtime.InteropServices.Marshal.Copy(dstValues, 0, dstPtr, dst_bytes);
39             // 解锁位图
40             srcBitmap.UnlockBits(srcBmData);
41             dstBitmap.UnlockBits(dstBmData);
42 
43             return imgData;
44         }
View Code

参考:  https://www.cnblogs.com/yiyiruohan/archive/2010/08/24/1807533.html

原文地址:https://www.cnblogs.com/mrguoguo/p/13588654.html