本次试验用的WINFORM ,要先绘制窗体 ,自己测试的时候注意对象名就可以了。
public Form1()
{
InitializeComponent();
}
static Mat mat1 = new Mat(@"timg.jpg", ImreadModes.AnyColor);
static Mat result = new Mat();
static OpenCvSharp.Point minLocation, maxLocation;
static Mat src = new Mat();
static Mat grayImage = new Mat();
static Mat ThresholdImage = new Mat();
static Bitmap bitmap, bitmap2, bitmap3;
static VideoCapture capture = new VideoCapture();
int a, b;
//运行摄像头
private void runVideo()
{
FrameSource frame = Cv2.CreateFrameSource_Camera(0);
while (true)
{
// capture.Read(mat1);
// VideoBox.Dispose();
frame.NextFrame(src);
grayImage = src.CvtColor(ColorConversionCodes.BGR2GRAY);
bitmap2 = BitmapConverter.ToBitmap(grayImage);
Cv2.Threshold(grayImage, ThresholdImage,a,b,ThresholdTypes.Binary);
bitmap3 = BitmapConverter.ToBitmap(ThresholdImage);
Action<Bitmap, Bitmap,Bitmap> action = showVideoBox; //委托
action(bitmap, bitmap2, bitmap3);
}
//while (true)
//{
// capture.Read(mat1);
// Cv2.ImShow("mat1", src);
// Cv2.WaitKey(100);
//}
}
//窗口异步传值的委托
private void showVideoBox( Image image, Image image2, Image image3)
{
Action<Image> action = deleVideoBox;
Action<Image> action2 = deleGrayBox;
Action<Image> action3 = deleThresholdBox;
VideoBox.BeginInvoke(action, image);
grayBox.BeginInvoke(action2, image2);
ThresholdBox.BeginInvoke(action3,image3);
}
//原视图
private void deleVideoBox( Image image)
{
Invalidate();
result.Create(src.Cols - mat1.Cols + 1, src.Rows - mat1.Cols + 1, MatType.CV_32FC1);
//进行匹配(1母图,2模版子图,3返回的result,4匹配模式_这里的算法比opencv少,具体可以看opencv的相关资料说明)
Cv2.MatchTemplate(src, mat1, result, TemplateMatchModes.SqDiff);
//对结果进行归一化(这里我测试的时候没有发现有什么用,但在opencv的书里有这个操作,应该有什么神秘加成,这里也加上)
Cv2.Normalize(result, result, 1, 0, NormTypes.MinMax, -1);
/// 通过函数 minMaxLoc 定位最匹配的位置
/// (这个方法在opencv里有5个参数,这里我写的时候发现在有3个重载,看了下可以直接写成拿到起始坐标就不取最大值和最小值了)
/// minLocation和maxLocation根据匹配调用的模式取不同的点
Cv2.MinMaxLoc(result, out minLocation, out maxLocation);
Cv2.Rectangle(src, minLocation, new OpenCvSharp.Point(minLocation.X + mat1.Cols, minLocation.Y + mat1.Rows), Scalar.Red, 2);
bitmap = BitmapConverter.ToBitmap(src);
VideoBox.Image = image;
VideoBox.Invalidate();
}
//灰度视图 (这里没用,不是主要的)
private void deleGrayBox(Image image)
{
Invalidate();
grayBox.Image = image;
grayBox.Invalidate();
}
//二值化视图(这里没用,不是主要的)
private void deleThresholdBox(Image image)
{
Invalidate();
ThresholdBox.Image = image;
ThresholdBox.Invalidate();
}
private void button1_Click(object sender, EventArgs e)
{
capture.Open(0);
Action action = runVideo;
action.BeginInvoke(null, null);
}
private void hScrollBar2_Scroll(object sender, ScrollEventArgs e)
{
a = hScrollBar2.Value;
label1.Text= hScrollBar2.Value.ToString();
}
private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
{
b = hScrollBar1.Value;
label2.Text = hScrollBar1.Value.ToString();
}
}
下面是绘制的窗 体:
实际上移动烟盒,只要在摄像头范围内,就能一直抓取到这个烟盒。