链接:https://pan.baidu.com/s/1pErTmMNXPNiTdfBSlTY8Sw
提取码:kbbq
2020.05.18更新
我把源码传到百度云了,需要的自取
链接:https://pan.baidu.com/s/1B6XFOKfxxhRf9jNNVhQH9A
提取码:5xzs
2020.04.09更新
这是去年五月份写的一个小软件了,当初就是用的这小程序拿到现在工作的机会,目前工作用的是C++和opencv,现在回来看当初写的东西还是有很多不成熟,大家如果有疑问可以下方留言,关于opencv的能回答就就回答,但是C#已经不用很久了,可能不能解答大家关于C#的疑问。后面看有空的花我写一些opencv的小技巧吧
从去年开始学习的python和opencv开发。
过年回来的时候面试公司内的自动化部门,面试通过且那边主管让我转到C#下开发软件(然而现在的部门处长不同意一直拖,弄到现在都没转调成),也一并学习了opencvsharp的使用。
在查阅资料的时候看到有位兄弟分享了自己写的一个小软件,收到启发决定自己也动手写一个程序,这样也加深对于C#和opencv库的使用和理解。
进入正题:
设计目的:
本次设计一个能够实现OpenCV部分功能的图像处理软件。目的在于方便图像处理人员在具体编写OpenCV程序前,提前能够对图像进行简单处理,进而帮助开发人员分析该如何对图像进行处理,C#中WinForm风格也让我想起大学时候学的C++下MFC的开发。
界面:
左边listbox是可以进行操作的方法,右侧的listbox是已经进行操作的内容,中间部分显示已进行处理的图像,中下部是操作流程。
窗体二是用于一些需要传递参数操作,比如模板匹配需要再传递另外一张图片和参数,可以根据再窗体一中选择的操作不同来显示修改或隐藏某些功能。
操作:
点击“打开图片”按钮选择一张图像文件,打开后中间部分就会显示图像内容。
需要什么操作双击左边listbox对应的选项即可完成对应操作,有些操作提供滑动条和参数的设定,这些都可以自己修改合适的 阈值,如果想重来点击“刷新图像”即可,这个按钮能删除已经进行的操作;
功能实现:
双击左侧选项触发listbox的double_click事件,通过将写好的listbox中选项的枚举,将选择的内容传递到处理函数中进行判断。
private void listBox1_DoubleClick(object sender, EventArgs e)
{
selectIndex = listBox1.SelectedIndex;
handle(selectIndex);//将选择的序号传到处理函数中
}
public enum lb1_list//记录listbox1操作方法
{
gray,
reverse,
binary,
gaussianBlur,
blur,
medianBlur,
bilateralFilter,
sobel,
scharr,
canny,
Laplacian,
carve,
rever_lr,
rever_tb,
frost,
sharp,
dilate,
erode,
tophat,
blackhat,
gamma,
log,
hist,
findContours,
template,
drawRect,
}
最后再根据枚举对应转换成int类型的数字找到方法
case (int)lb1_list.binary:
Cv2.ImShow("二值化处理", pictureMain);
Mat temp0 = new Mat();
pictureMain.CopyTo(temp0);
CvTrackbarCallback2 ctbc0 = new CvTrackbarCallback2(binary);
CvTrackbar cvtb0 = new CvTrackbar("程度", "二值化处理", 0, 10, ctbc0, temp0);
display("二值化");
break;
最终我们就可以通过不同操作来预先判断我们图像在实际开发中需要进行怎么样的处理了。
下面贴附Form1源码:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void intrudBtn_Load(object sender, EventArgs e)
{
}
public Mat pictureMain;//当前主窗体图像
public Mat form2image;//窗体二图像
public float form2Num1=50f;
public float form2Num2 = 150f;//接受窗体二传入的参数一参数二
string imageName;
private void openBtn_Click(object sender, EventArgs e)
{
OpenFileDialog ofd1 = new OpenFileDialog();//创建打开文件夹窗体
ofd1.Title = "请选择输入的图像";
ofd1.InitialDirectory = @"";//初始化目录
ofd1.Multiselect = false;//不可多选
ofd1.Filter = "图像文件|*.jpg;*.png;*.bmp|全部文件|*.*";
ofd1.ShowDialog();
if (ofd1.FileName!=string.Empty)
{
try
{
pictureShow.Load(ofd1.FileName);
imageName = ofd1.FileName;
textBox1.AppendText("\n\r打开文件:" + imageName);
textBox1.SelectionStart = this.textBox1.TextLength;
textBox1.ScrollToCaret();
pictureMain = new Mat(ofd1.FileName);
}
catch (Exception)
{
MessageBox.Show("打开失败,请检查文件格式是否符合");
}
}
}
private void saveBtn_Click(object sender, EventArgs e)
{
if (pictureShow!=null)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Title = "保存文件";
sfd.Filter = "JPGE图像|*.jpg|PNG图像|*.png|BMP图像|*.bmp|所有文件|*.*";
sfd.InitialDirectory = Environment.CurrentDirectory;
sfd.ShowDialog();
if (sfd.FileName != null)
{
try
{
pictureShow.Image.Save(sfd.FileName);
textBox1.AppendText("\r\n图片已保存至:" + sfd.FileName);
textBox1.SelectionStart = textBox1.TextLength;
textBox1.ScrollToCaret();
}
catch (Exception)
{
}
}
}
else
{
MessageBox.Show("无可保存图片");
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("本人第一个以C#和opencvsharp写的小程序,很多bug来不及慢慢优化,但也算包含一番心血,主要是将之前学习的内容再复习深化了解,感叹路漫漫其修远兮,昨日之日不可留,最终走回程序员这条路");
}
private void reflashBtn_Click(object sender, EventArgs e)
{
num = 1;
listBox2.Items.Clear();
textBox1.Text = "以下为通知信息:";
if (imageName != string.Empty)
{
try
{
pictureShow.Load(imageName);
pictureMain = new Mat(imageName);
pictureShow.Image = pictureMain.ToBitmap();
}
catch { }
}
}
int num = 1;//记录处理次数
public enum lb1_list//记录操作方法
{
gray,
reverse,
binary,
gaussianBlur,
blur,
medianBlur,
bilateralFilter,
sobel,
scharr,
canny,
Laplacian,
carve,
rever_lr,
rever_tb,
frost,
sharp,
dilate,
erode,
tophat,
blackhat,
gamma,
log,
hist,
findContours,
template,
drawRect,
}
public int selectIndex;
/// <summary>
/// 实现双击启动处理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void listBox1_DoubleClick(object sender, EventArgs e)
{
selectIndex = listBox1.SelectedIndex;
handle(selectIndex);
}
/// <summary>
/// 二值化Tbar处理函数
/// </summary>
/// <param name="pos"></param>
/// <param name="userdata"></param>
public void binary(int pos, object userdata)
{
Mat a = (Mat)userdata;
Mat b = new Mat();
a.CopyTo(b);
Cv2.Threshold(b, b, pos * 25, 255, ThresholdTypes.Binary);
Cv2.ImShow("二值化处理", b);
b.CopyTo(pictureMain);
pictureShow.Image = pictureMain.ToBitmap();
b.Release();
}
/// <summary>
/// 高斯滤波
/// </summary>
/// <param name="pos"></param>
/// <param name="userdata"></param>
public void gaussianBlur(int pos,object userdata)
{
Mat src = (Mat)userdata;
Mat a = new Mat();
src.CopyTo(a);
Cv2.GaussianBlur(a, a, new OpenCvSharp.Size(pos*2+1, pos*2+1), 5);
Cv2.ImShow("高斯滤波", a);
a.CopyTo(pictureMain);
pictureShow.Image = a.ToBitmap();
a.Release();
}
/// <summary>
/// 均值滤波
/// </summary>
/// <param name="pos"></param>
/// <param name="userdata"></param>
public void blur(int pos,object userdata)
{
Mat src = (Mat)userdata;
Mat a = new Mat();
src.CopyTo(a);
Cv2.Blur(a, a, new OpenCvSharp.Size(pos+1, pos+1));
Cv2.ImShow("均值滤波", a);
a.CopyTo(pictureMain);
pictureShow.Image = a.ToBitmap();
a.Release();
}
public void medianBlur(int pos, object userdata)
{
Mat src = (Mat)userdata;
Mat a = new Mat();
src.CopyTo(a);
Cv2.MedianBlur(a, a, pos*2+1);
Cv2.ImShow("中值滤波", a);
a.CopyTo(pictureMain);
pictureShow.Image = a.ToBitmap();
a.Release();
}
public void bilateralFilter(int pos, object userdata)
{
Mat src = (Mat)userdata;
Mat a = new Mat();
Mat b = new Mat();
src.CopyTo(b);
Cv2.BilateralFilter(b, a, pos*5 + 1, 100, 100);
Cv2.ImShow("双边滤波", a);
a.CopyTo(pictureMain);
pictureShow.Image = a.ToBitmap();
a.Release();
b.Release();
}
public void canny(int pos,object userdata)
{
Mat src = (Mat)userdata;
Mat a = new Mat();
src.CopyTo(a);
Cv2.Canny(a, a, pos * 25, pos * 25);
Cv2.ImShow("canny边缘检测", a);
a.CopyTo(pictureMain);
pictureShow.Image = a.ToBitmap();
a.Release();
Thread.Sleep(50);
}
public void laplacian(int pos,object userdata)
{
Mat src=(Mat)userdata;
Mat a = new Mat();
src.CopyTo(a);
Cv2.Laplacian(a, a, -1, pos*2 + 1);
Cv2.ImShow("Laplacian边缘检测", a);
a.CopyTo(pictureMain);
pictureShow.Image = a.ToBitmap();
a.Release();
}
public void dilate(int pos,object userdata)
{
Mat src = (Mat)userdata;
Mat a = new Mat();
src.CopyTo(a);
Mat structureElement = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(pos * 2 + 1, pos * 2 + 1));
Cv2.Dilate(a, a, structureElement);
Cv2.ImShow("膨胀处理", a);
a.CopyTo(pictureMain);
pictureShow.Image = a.ToBitmap();
a.Release();
}
public void erode(int pos,object userdata)
{
Mat src = (Mat)userdata;
Mat a = new Mat();
src.CopyTo(a);
Mat structureElement = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(pos * 2 + 1, pos * 2 + 1));
Cv2.Erode(a, a, structureElement);
Cv2.ImShow("腐蚀处理", a);
a.CopyTo(pictureMain);
pictureShow.Image = a.ToBitmap();
a.Release();
}
public void tophat(int pos,object userdata)
{
Mat src = (Mat)userdata;
Mat a = new Mat();
src.CopyTo(a);
Mat stuctureElement = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(pos+1, pos+1), new OpenCvSharp.Point(-1, -1));
Cv2.MorphologyEx(a, a, MorphTypes.TopHat, stuctureElement);
Cv2.ImShow("顶帽处理", a);
a.CopyTo(pictureMain);
pictureShow.Image = pictureMain.ToBitmap();
a.Release();
}
public void blackhat(int pos, object userdata)
{
Mat src = (Mat)userdata;
Mat a = new Mat();
src.CopyTo(a);
Mat stuctureElement = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(pos + 1, pos + 1), new OpenCvSharp.Point(-1, -1));
Cv2.MorphologyEx(a, a, MorphTypes.BlackHat, stuctureElement);
Cv2.ImShow("黑帽处理", a);
a.CopyTo(pictureMain);
pictureShow.Image = pictureMain.ToBitmap();
a.Release();
}
public void drawRect(int pos,object userdata)
{
Mat src = (Mat)userdata;
Mat a = new Mat();
Mat gray = new Mat();
src.CopyTo(gray);
if (gray.Channels()==3)
{
Cv2.CvtColor(gray, gray, ColorConversionCodes.BGR2GRAY);
}
gray.CopyTo(a);
Cv2.Threshold(~a, a ,pos *25, 255, ThresholdTypes.Binary);
//Cv2.Canny(a, a, pos*10, 255);
HierarchyIndex[] hierarchy;
OpenCvSharp.Point[][] coutours;
Cv2.FindContours(a, out coutours,out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxNone);
OpenCvSharp.Point[][] contours_ploy = new OpenCvSharp.Point[coutours.Length][];
RotatedRect[] RotatedRect_ploy = new RotatedRect[coutours.Length];
Rect[] rect_poly = new Rect[coutours.Length];
for (int i = 0; i < coutours.Length; i++)
{
contours_ploy[i] = Cv2.ApproxPolyDP(coutours[i], 10, true);//计算凸包
rect_poly[i] = Cv2.BoundingRect(coutours[i]);//最小外接矩形,我们不用,
if (contours_ploy[i].Length>5)//拟合的线条数不少于5
{
RotatedRect temp1 = Cv2.MinAreaRect(contours_ploy[i]);//最小外接矩形,能旋转
RotatedRect_ploy[i] = temp1;//将该矩形放入集合中
}
}
Point2f[] pot = new Point2f[4];
for (int i = 0; i < RotatedRect_ploy.Length; i++)
{
pot = RotatedRect_ploy[i].Points();
double line1 = Math.Sqrt((pot[1].Y - pot[0].Y) * (pot[1].Y - pot[0].Y)+ (pot[1].X - pot[0].X) * (pot[1].X - pot[0].X));
double line2=Math.Sqrt((pot[3].Y - pot[0].Y) * (pot[3].Y - pot[0].Y) + (pot[3].X - pot[0].X) * (pot[3].X - pot[0].X));
if (line1*line2<9000)//太小直接pass
{
continue;
}
for (int j = 0; j < 4; j++)
{
Cv2.Line(pictureMain, (OpenCvSharp.Point)pot[j], (OpenCvSharp.Point)pot[(j + 1) % 4], Scalar.Green,3);
}
}
Cv2.ImShow("最小外包矩形", a);
pictureShow.Image = pictureMain.ToBitmap();
a.Release();
}
public void handle(int selectIndex)
{
switch (selectIndex)
{
case (int)lb1_list.gray:
if (pictureMain.Channels() == 3)
{
Cv2.CvtColor(pictureMain, pictureMain, ColorConversionCodes.BGR2GRAY);
pictureShow.Image = pictureMain.ToBitmap();
display("灰度化");
}
else
{
MessageBox.Show("已是灰度图像,不要重复操作");
}
break;
case (int)lb1_list.reverse:
pictureMain = ~pictureMain;
pictureShow.Image = pictureMain.ToBitmap();
display("反色");
break;
case (int)lb1_list.binary:
Cv2.ImShow("二值化处理", pictureMain);
Mat temp0 = new Mat();
pictureMain.CopyTo(temp0);
CvTrackbarCallback2 ctbc0 = new CvTrackbarCallback2(binary);
CvTrackbar cvtb0 = new CvTrackbar("程度", "二值化处理", 0, 10, ctbc0, temp0);
display("二值化");
break;
case (int)lb1_list.gaussianBlur:
Cv2.ImShow("高斯滤波", pictureMain);
Mat temp1 = new Mat();
pictureMain.CopyTo(temp1);
CvTrackbarCallback2 ctbc1 = new CvTrackbarCallback2(gaussianBlur);
CvTrackbar cvtb1 = new CvTrackbar("程度", "高斯滤波", 0, 10, ctbc1, temp1);
display("高斯滤波");
break;
case (int)lb1_list.blur:
Cv2.ImShow("均值滤波", pictureMain);
Mat temp2 = new Mat();
pictureMain.CopyTo(temp2);
CvTrackbarCallback2 ctbc2 = new CvTrackbarCallback2(blur);
CvTrackbar cvtb2 = new CvTrackbar("程度", "均值滤波", 0, 10, ctbc2, temp2);
display("均值滤波");
break;
case (int)lb1_list.medianBlur:
Cv2.ImShow("中值滤波", pictureMain);
Mat temp3 = new Mat();
pictureMain.CopyTo(temp3);
CvTrackbarCallback2 ctbc3 = new CvTrackbarCallback2(medianBlur);
CvTrackbar cvtb3 = new CvTrackbar("程度", "中值滤波", 0, 10, ctbc3, temp3);
display("中值滤波");
break;
case (int)lb1_list.bilateralFilter:
Cv2.ImShow("双边滤波", pictureMain);
Mat temp4 = new Mat();
pictureMain.CopyTo(temp4);
CvTrackbarCallback2 crbc4 = new CvTrackbarCallback2(bilateralFilter);
CvTrackbar cvtb4 = new CvTrackbar("程度", "双边滤波", 0, 10, crbc4, temp4);
display("双边滤波");
break;
case (int)lb1_list.sobel://-1 -2 -1
Mat sobelx = new Mat();
Mat sobely = new Mat();
Cv2.Sobel(pictureMain, sobelx, -1, 1, 0);
Cv2.Sobel(pictureMain, sobely, -1, 0, 1);
Cv2.AddWeighted(sobelx, 0.5, sobely, 0.5, 0, pictureMain);//gamma为加到结果上的值
pictureShow.Image = pictureMain.ToBitmap();
display("sobel边缘检测");
break;
case (int)lb1_list.scharr://-3 -10 -3
Mat scharrx = new Mat();
Mat scharry = new Mat();
Cv2.Scharr(pictureMain, scharrx, -1, 1, 0);
Cv2.Scharr(pictureMain, scharry, -1, 0, 1);
Cv2.AddWeighted(scharrx, 0.5, scharry, 0.5, 0, pictureMain);
pictureShow.Image = pictureMain.ToBitmap();
display("scharr边缘检测");
break;
case (int)lb1_list.canny:
Cv2.ImShow("canny边缘检测", pictureMain);
Mat temp_canny = new Mat();
pictureMain.CopyTo(temp_canny);
if (temp_canny.Channels() == 3)
{
Cv2.CvtColor(temp_canny, temp_canny, ColorConversionCodes.BGR2GRAY);
}
CvTrackbarCallback2 ctbc_canny = new CvTrackbarCallback2(canny);
CvTrackbar cvtb_canny = new CvTrackbar("程度", "canny边缘检测", 0, 10, ctbc_canny, temp_canny);
display("canny边缘检测");
break;
case (int)lb1_list.Laplacian:
Cv2.ImShow("Laplacian边缘检测", pictureMain);
Mat temp_Laplacian = new Mat();
pictureMain.CopyTo(temp_Laplacian);
CvTrackbarCallback2 ctbc_Laplacian = new CvTrackbarCallback2(laplacian);
CvTrackbar cvrb_laplacian = new CvTrackbar("程度", "Laplacian边缘检测", 0, 10, ctbc_Laplacian, temp_Laplacian);
display("laplacian边缘检测");
break;
case (int)lb1_list.carve:
if (pictureMain.Channels() != 1)
{
Cv2.CvtColor(pictureMain, pictureMain, ColorConversionCodes.BGR2GRAY);
}
for (int i = 0; i < pictureMain.Rows; i++)
{
for (int j = 0; j < pictureMain.Cols; j++)
{
int newP = 2 * pictureMain.Get<byte>(i, j) - pictureMain.Get<byte>(i, j + 1) - pictureMain.Get<byte>(i + 1, j) + 100;
if (newP > 255)
{
newP = 255;
}
else if (newP < 0)
{
newP = 0;
}
pictureMain.Set(i, j, (byte)newP);
}
}
pictureShow.Image = pictureMain.ToBitmap();
display("浮雕");
break;
case (int)lb1_list.rever_lr:
Mat imx_lr = new Mat(pictureMain.Size(), MatType.CV_32FC1);
Mat imy_lr = new Mat(pictureMain.Size(), MatType.CV_32FC1);
for (int i = 0; i < pictureMain.Rows; i++)
{
for (int j = 0; j < pictureMain.Cols; j++)
{
imx_lr.Set(i, j, (float)(pictureMain.Cols - j - 1));
imy_lr.Set(i, j, (float)i);
}
}
Cv2.Remap(pictureMain, pictureMain, imx_lr, imy_lr);
pictureShow.Image = pictureMain.ToBitmap();
display("左右反转");
break;
case (int)lb1_list.rever_tb:
Mat imx_tb = new Mat(pictureMain.Size(), MatType.CV_32FC1);
Mat imy_tb = new Mat(pictureMain.Size(), MatType.CV_32FC1);
for (int i = 0; i < pictureMain.Rows; i++)
{
for (int j = 0; j < pictureMain.Cols; j++)
{
imx_tb.Set(i, j, (float)j);
imy_tb.Set(i, j, (float)(pictureMain.Rows - i - 1));
}
}
Cv2.Remap(pictureMain, pictureMain, imx_tb, imy_tb);
pictureShow.Image = pictureMain.ToBitmap();
display("上下反转");
break;
case (int)lb1_list.frost:
Mat imx_frost = new Mat(pictureMain.Size(), MatType.CV_32FC1);
Mat imy_frost = new Mat(pictureMain.Size(), MatType.CV_32FC1);
Random rm = new Random();
for (int i = 0; i < pictureMain.Rows; i++)
{
for (int j = 0; j < pictureMain.Cols; j++)
{
imx_frost.Set(i, j, (float)(j + rm.Next(-5, 5)));
imy_frost.Set(i, j, (float)(i + rm.Next(-5, 5)));
}
}
Cv2.Remap(pictureMain, pictureMain, imx_frost, imy_frost);
pictureShow.Image = pictureMain.ToBitmap();
display("毛玻璃");
break;
case (int)lb1_list.sharp:
Mat mask = new Mat(new OpenCvSharp.Size(3, 3), MatType.CV_32FC1);
mask.Set<float>(0, 1, -1); mask.Set<float>(1, 0, -1); mask.Set<float>(1, 1, 5); mask.Set<float>(1, 2, -1); mask.Set<float>(2, 1, -1);
Mat temp_sharp = new Mat();
pictureMain.CopyTo(temp_sharp);
Cv2.Filter2D(pictureMain, temp_sharp, -1, mask);
Cv2.WaitKey(500);
temp_sharp.CopyTo(pictureMain);
pictureShow.Image = temp_sharp.ToBitmap();
display("锐化");
mask.Release();
temp_sharp.Release();
break;
case (int)lb1_list.dilate:
Cv2.ImShow("膨胀处理", pictureMain);
Mat temp_dilate = new Mat();
pictureMain.CopyTo(temp_dilate);
CvTrackbarCallback2 ctbc_dilate = new CvTrackbarCallback2(dilate);
CvTrackbar cvtb_dilate = new CvTrackbar("程度", "膨胀处理", 0, 10, ctbc_dilate, temp_dilate);
display("膨胀");
break;
case (int)lb1_list.erode:
Cv2.ImShow("腐蚀处理", pictureMain);
Mat temp_erode = new Mat();
pictureMain.CopyTo(temp_erode);
CvTrackbarCallback2 ctbc_erode = new CvTrackbarCallback2(erode);
CvTrackbar cvtb_erode = new CvTrackbar("程度", "腐蚀处理", 0, 10, ctbc_erode, temp_erode);
display("腐蚀");
break;
case (int)lb1_list.gamma:
if (pictureMain.Channels() == 1)
{
Mat temp_gray = new Mat(pictureMain.Size(), MatType.CV_16UC1);
for (int i = 0; i < pictureMain.Rows; i++)
{
for (int j = 0; j < pictureMain.Cols; j++)
{
temp_gray.Set(i, j, Math.Abs(pictureMain.Get<byte>(i, j) * pictureMain.Get<byte>(i, j)));//因为pictureMain为8UC1,所以这里一定要使用<byte>,不能使用其他类型
}
}
Cv2.Normalize(temp_gray, temp_gray, 0, 255, NormTypes.MinMax);
Cv2.ConvertScaleAbs(temp_gray, temp_gray);
temp_gray.CopyTo(pictureMain);
pictureShow.Image = pictureMain.ToBitmap();
temp_gray.Release();
}
else
{
Mat temp_gamma = new Mat(pictureMain.Size(), MatType.CV_32FC3);
Vec3f channels = new Vec3f();
for (int i = 0; i < pictureMain.Rows; i++)
{
for (int j = 0; j < pictureMain.Cols; j++)
{
channels.Item0 = Math.Abs(pictureMain.Get<Vec3b>(i, j).Item0 * pictureMain.Get<Vec3b>(i, j).Item0);
channels.Item1 = Math.Abs(pictureMain.Get<Vec3b>(i, j).Item1 * pictureMain.Get<Vec3b>(i, j).Item1);
channels.Item2 = Math.Abs(pictureMain.Get<Vec3b>(i, j).Item2 * pictureMain.Get<Vec3b>(i, j).Item2);
temp_gamma.Set(i, j, channels);
}
}
Cv2.Normalize(temp_gamma, temp_gamma, 0, 255, NormTypes.MinMax);
Cv2.ConvertScaleAbs(temp_gamma, temp_gamma);
temp_gamma.CopyTo(pictureMain);
pictureShow.Image = pictureMain.ToBitmap();
temp_gamma.Release();
}
display("gamma调整");
break;
case (int)lb1_list.log:
Mat[] temp_log = pictureMain.Split();
for (int i = 0; i < pictureMain.Rows; i++)
{
for (int j = 0; j < pictureMain.Cols; j++)
{
temp_log[0].Set(i, j, Math.Log(temp_log[0].Get<float>(i, j), 1.2));
temp_log[1].Set(i, j, Math.Log(temp_log[1].Get<float>(i, j), 1.2));
temp_log[2].Set(i, j, Math.Log(temp_log[2].Get<float>(i, j), 1.2));
}
}
Cv2.Merge(temp_log, pictureMain);
Cv2.Normalize(pictureMain, pictureMain, 0, 255, NormTypes.MinMax);
pictureShow.Image = pictureMain.ToBitmap();
//Mat temp_log = new Mat(pictureMain.Size(), MatType.CV_8UC3);
//pictureMain.CopyTo(temp_log);
//if (pictureMain.Channels()==3)
//{
// Vec3i channels = new Vec3i();
// for (int i = 0; i < pictureMain.Rows; i++)
// {
// for (int j = 0; j < pictureMain.Cols; j++)
// {
// //float a = pictureMain.Get<Vec3b>(i, j).Item0;
// //float b = pictureMain.Get<Vec3b>(i, j).Item1;
// //float c = pictureMain.Get<Vec3b>(i, j).Item2;
// channels.Item0 = (int)Math.Log(pictureMain.Get<Vec3b>(i, j).Item0,1.2);
// channels.Item1 = (int)Math.Log(pictureMain.Get<Vec3b>(i, j).Item1,1.2);
// channels.Item2 = (int)Math.Log(pictureMain.Get<Vec3b>(i, j).Item2,1.2);
// temp_log.Set<Vec3i>(i, j, channels);
// }
// }//这个操作有毒,不能归一化,还把GR通道置0,放弃
//temp_log.Normalize(255,0, NormTypes.MinMax);
//float e1 = temp_log.Get<Vec3b>(0,0).Item0;
//float f = temp_log.Get<Vec3b>(0,0).Item1;
//float g = temp_log.Get<Vec3b>(0, 0).Item2;
//Cv2.Normalize(temp_log, temp_log, 0, 255, NormTypes.MinMax);
//Cv2.ConvertScaleAbs(temp_log, temp_log);
//temp_log.CopyTo(pictureMain);
//pictureShow.Image = pictureMain.ToBitmap();
//temp_log.Release();
display("log亮部增强");
break;
case (int)lb1_list.tophat:
Mat temp_tophat = new Mat();
pictureMain.CopyTo(temp_tophat);
Cv2.ImShow("顶帽处理", pictureMain);
CvTrackbarCallback2 ctbc_topat = new CvTrackbarCallback2(tophat);
CvTrackbar cvtb_tophat = new CvTrackbar("程度", "顶帽处理", 0, 20, ctbc_topat, temp_tophat);
pictureShow.Image = pictureMain.ToBitmap();
display("顶帽");
break;
case (int)lb1_list.blackhat:
Mat temp_blackhat = new Mat();
pictureMain.CopyTo(temp_blackhat);
Cv2.ImShow("黑帽处理", pictureMain);
CvTrackbarCallback2 ctbc_blackhat = new CvTrackbarCallback2(blackhat);
CvTrackbar cvtb_blackhat = new CvTrackbar("程度", "黑帽处理", 0, 20, ctbc_blackhat, temp_blackhat);
pictureShow.Image = pictureMain.ToBitmap();
display("黑帽");
break;
case (int)lb1_list.hist:
if (pictureMain.Channels() == 1)
{
Mat[] image = { pictureMain };
Mat temp_hist = pictureMain;
int[] channels = new int[] { 0 };
int[] histsize = new int[] { 256 };
Mat mask_hist = new Mat();
Mat hist = new Mat();
Rangef[] range = new Rangef[1];
range[0].Start = 0f;
range[0].End = 256f;
Cv2.CalcHist(image, channels, mask_hist, hist, 1, histsize, range);
Mat histImage = new Mat(256, 256, MatType.CV_8UC3);
double minValue, maxValue;
Cv2.MinMaxLoc(hist, out minValue, out maxValue);
for (int i = 0; i < 256; i++)
{
int len = (int)(hist.Get<float>(i) / maxValue * 256);
Cv2.Line(histImage, i, histImage.Rows, i, histImage.Rows - len, Scalar.White, 2);
}
Cv2.ImShow("灰度图像直方图", histImage);
}
else
{
Mat[] images = pictureMain.Split();
Mat[] bImage = { images[0] };
Mat[] gImage = { images[1] };
Mat[] rImage = { images[2] };
Mat mask_hist = new Mat();
Mat[] hists = { new Mat(), new Mat(), new Mat() };
int[] channels = { 0 };
int[] histSize = { 256 };
Rangef[] range = new Rangef[1];
range[0].Start = 0f;
range[0].End = 256f;
Cv2.CalcHist(bImage, channels, mask_hist, hists[0], 1, histSize, range);//dim为需要统计直方图通道的个数
Cv2.CalcHist(gImage, channels, mask_hist, hists[1], 1, histSize, range);
Cv2.CalcHist(rImage, channels, mask_hist, hists[2], 1, histSize, range);
Mat[] histImage = { new Mat(256, 256, MatType.CV_8UC3), new Mat(256, 256, MatType.CV_8UC3), new Mat(256, 256, MatType.CV_8UC3) };
Scalar[] color = { Scalar.Blue, Scalar.Green, Scalar.Red };
for (int i = 0; i < 3; i++)
{
double minVal = 0f;
double maxVal = 0f;
Cv2.MinMaxLoc(hists[i], out minVal, out maxVal);
for (int j = 0; j < 256; j++)
{
int len = (int)(hists[i].Get<float>(j) / maxVal * 256);
Cv2.Line(histImage[i], j, histImage[0].Rows, j, histImage[0].Rows - len, color[i], 2);
}
}
Cv2.ImShow("b", histImage[0]);
Cv2.ImShow("g", histImage[1]);
Cv2.ImShow("r", histImage[2]);
}
display("直方图显示");
break;
case (int)lb1_list.findContours:
MessageBox.Show("假如卡死了,是计算量太大的缘故,请重新调整canny参数一参数二,默认参数一50,参数二150");
Mat temp_find = new Mat();
if (pictureMain.Channels() == 3)
{
Cv2.CvtColor(pictureMain, temp_find, ColorConversionCodes.BGR2GRAY);
}
Cv2.Canny(temp_find, temp_find, form2Num1, form2Num2);
HierarchyIndex[] hierarchy;
OpenCvSharp.Point[][] coutours;
Cv2.FindContours(temp_find, out coutours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxNone);
for (int i = 0; i < coutours.Length; i++)
{
Cv2.DrawContours(pictureMain, coutours, i, Scalar.RandomColor(), 1);
}
pictureShow.Image = pictureMain.ToBitmap();
display("绘制轮廓");
break;
case (int)lb1_list.template:
if (form2image != null && pictureMain.Rows > form2image.Rows && pictureMain.Cols > form2image.Cols)
{
Mat result = new Mat(pictureMain.Cols - form2image.Cols, pictureMain.Rows - form2image.Cols, MatType.CV_32FC1);
Cv2.MatchTemplate(pictureMain, form2image, result, TemplateMatchModes.CCoeff);
double maxVal, minVal;
OpenCvSharp.Point minLoc, maxLoc;
Cv2.Normalize(result, result, 0, 1, NormTypes.MinMax);
Cv2.MinMaxLoc(result, out minVal, out maxVal, out minLoc, out maxLoc);
Cv2.ImShow("匹配的图像", form2image);
pictureMain.Rectangle(maxLoc, new OpenCvSharp.Point(maxLoc.X + form2image.Cols, maxLoc.Y + form2image.Rows), Scalar.Red);
pictureShow.Image = pictureMain.ToBitmap();
textBox1.AppendText("\r\n模板匹配程度为:" + minVal * 100 + " % ");
}
else if (form2image == null)
{
MessageBox.Show("请在窗口二中传入匹配图像");
}
else
{
MessageBox.Show("匹配图像需要比原始图像小");
}
display("模板匹配");
break;
case (int)lb1_list.drawRect:
Cv2.ImShow("最小外包矩形", pictureMain);
Mat tempRect = new Mat();
pictureMain.CopyTo(tempRect);
CvTrackbarCallback2 crbc_rect = new CvTrackbarCallback2(drawRect);
CvTrackbar cvtb_rect = new CvTrackbar("程度", "最小外包矩形", 0, 20, crbc_rect, tempRect);
MessageBox.Show("这个处理内存占用巨大,不要拖动太多次");
break;
default:
break;
}
}
/// <summary>
/// 图像处理后更新信息
/// </summary>
/// <param name="name"></param>
public void display(string name)
{
textBox1.AppendText("\r\n图像运行"+ name+ "处理成功");
textBox1.SelectionStart = this.textBox1.TextLength;
textBox1.ScrollToCaret();
listBox2.Items.Add(num + ". "+ name);
num++;
}
private void button2_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
form2.Show(this);
}
private void initalBtn_Click(object sender, EventArgs e)
{
pictureMain = null;
pictureShow.Image = null;
num = 1;
listBox2.Items.Clear();
textBox1.Text = "以下为通知信息:";
}
}```
参考地址:https://blog.csdn.net/you_big_father/article/details/86088531