We have made it!
| 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; | |
| using Emgu.CV; | |
| using Emgu.CV.Structure; | |
| using Emgu.CV.Cvb; | |
| using Emgu.CV.CvEnum; | |
| namespace Hakaton | |
| { | |
| public partial class Form1 : Form | |
| { | |
| private VideoCapture videoCapture; | |
| private bool detectFire; | |
| private bool frameSkip = true; | |
| private double redThreshold = 220; | |
| private double whiteThreshold = 220; | |
| private int frameInterval = 1000 / 30; | |
| private Timer fpsTimer; | |
| public Form1() | |
| { | |
| InitializeComponent(); | |
| Init(); | |
| } | |
| private void Init() | |
| { | |
| picPreview.SizeMode = PictureBoxSizeMode.StretchImage; | |
| picRedFilter.SizeMode = PictureBoxSizeMode.StretchImage; | |
| picFinal.SizeMode = PictureBoxSizeMode.StretchImage; | |
| trbSeek.Enabled = false; | |
| } | |
| private void OpenVideo(string filename) | |
| { | |
| videoCapture = new VideoCapture(filename); | |
| int frameCount = (int) videoCapture.GetCaptureProperty(CapProp.FrameCount); | |
| trbSeek.Minimum = 0; | |
| trbSeek.Maximum = frameCount; | |
| trbSeek.Value = 0; | |
| trbSeek.Enabled = true; | |
| fpsTimer = new Timer(); | |
| fpsTimer.Interval = frameInterval; | |
| fpsTimer.Tick += ProcessFrame; | |
| fpsTimer.Start(); | |
| } | |
| private void OpenCamera() | |
| { | |
| videoCapture = new VideoCapture(); | |
| trbSeek.Enabled = false; | |
| frameSkip = false; | |
| Application.Idle += ProcessFrame; | |
| } | |
| private void ProcessFrame(object sender, EventArgs e) | |
| { | |
| DateTime methodStart = DateTime.Now; | |
| Image<Bgr, Byte> redFiltered = null; | |
| Image<Bgr, Byte> ycbcrFiltered = null; | |
| Image<Gray, Byte> blobImage = null; | |
| Image<Bgr, Byte> rawFrame = videoCapture.QueryFrame().ToImage<Bgr, Byte>(); | |
| rawFrame = rawFrame.Resize(320, 240, Emgu.CV.CvEnum.Inter.Cubic); | |
| rawFrame._EqualizeHist(); | |
| if (detectFire) | |
| { | |
| redFiltered = redTreshhold(rawFrame); | |
| ycbcrFiltered = yCbCrThreshold(redFiltered); | |
| blobImage = binaryTreshold(ycbcrFiltered); | |
| CvBlobs blobs = new CvBlobs(); | |
| CvBlobDetector blobDetector = new CvBlobDetector(); | |
| uint blobCount = blobDetector.Detect(blobImage, blobs); | |
| int minArea = (int)(rawFrame.Width * rawFrame.Height * 0.002); | |
| foreach (KeyValuePair<uint, CvBlob> blobPair in blobs) | |
| { | |
| if(blobPair.Value.Area > minArea) | |
| { | |
| Rectangle rect = blobPair.Value.BoundingBox; | |
| rawFrame.Draw(rect, new Bgr(0, 255, 0), 5); | |
| } | |
| } | |
| } | |
| picPreview.Image = rawFrame.Bitmap; | |
| if(detectFire) | |
| { | |
| picRedFilter.Image = redFiltered.Bitmap; | |
| picFinal.Image = blobImage.Bitmap; | |
| } | |
| else | |
| { | |
| picRedFilter.Image = null; | |
| picFinal.Image = null; | |
| } | |
| if(frameSkip) | |
| { | |
| int timePassed = (DateTime.Now - methodStart).Milliseconds; | |
| int framesToSkip = timePassed / frameInterval; | |
| for (int i = 0; i < framesToSkip; i++) | |
| videoCapture.QueryFrame(); | |
| } | |
| int currentFrame = (int) videoCapture.GetCaptureProperty(CapProp.PosFrames); | |
| int frameCount = (int) videoCapture.GetCaptureProperty(CapProp.FrameCount); | |
| if(currentFrame != -1 && frameCount != -1) | |
| { | |
| trbSeek.Value = currentFrame; | |
| if (currentFrame == frameCount) | |
| CloseVideo(); | |
| } | |
| } | |
| private void CloseVideo() | |
| { | |
| fpsTimer.Stop(); | |
| picPreview.Image = null; | |
| picRedFilter.Image = null; | |
| picFinal.Image = null; | |
| } | |
| Image<Gray, Byte> binaryTreshold(Image<Bgr, Byte> originalImage) | |
| { | |
| Image<Gray, Byte> newImage = new Image<Gray, byte>(originalImage.Width, originalImage.Height); | |
| Bgr black = new Bgr(0, 0, 0); | |
| for (int y = 0; y < originalImage.Height; y++) | |
| { | |
| for (int x = 0; x < originalImage.Width; x++) | |
| { | |
| if (originalImage[y, x].Equals(black)) | |
| newImage[y, x] = new Gray(0); | |
| else | |
| newImage[y, x] = new Gray(255); | |
| } | |
| } | |
| return newImage; | |
| } | |
| Image<Bgr, Byte> redTreshhold(Image<Bgr, Byte> originalImage) | |
| { | |
| Image<Bgr, Byte> newImage = new Image<Bgr, byte>(originalImage.Width, originalImage.Height); | |
| for (int y = 0; y < originalImage.Height; y++) | |
| { | |
| for (int x = 0; x < originalImage.Width; x++) | |
| { | |
| double r = originalImage[y, x].Red; | |
| double g = originalImage[y, x].Green; | |
| double b = originalImage[y, x].Blue; | |
| bool isFire = false; | |
| if (r > g && r > b) | |
| if (r > redThreshold) | |
| isFire = true; | |
| if (r > whiteThreshold && g > whiteThreshold && b > whiteThreshold) | |
| isFire = true; | |
| if (isFire) | |
| newImage[y, x] = originalImage[y, x]; | |
| else | |
| newImage[y, x] = new Bgr(0, 0, 0); | |
| } | |
| } | |
| return newImage; | |
| } | |
| Image<Bgr, Byte> yCbCrThreshold(Image<Bgr, Byte> originalImage) | |
| { | |
| Image<Bgr, Byte> newImage = new Image<Bgr, byte>(originalImage.Width, originalImage.Height); | |
| for (int Y = 0; Y < originalImage.Height; Y++) | |
| { | |
| for (int X = 0; X < originalImage.Width; X++) | |
| { | |
| double rRaw = originalImage[Y, X].Red; | |
| double gRaw = originalImage[Y, X].Green; | |
| double bRaw = originalImage[Y, X].Blue; | |
| double r = rRaw / 255; | |
| double g = gRaw / 255; | |
| double b = bRaw / 255; | |
| double y = 0.299 * r + 0.587 * g + 0.114 * b; | |
| double cB = -0.168736 * r + -0.331264 * g + 0.500 * b; | |
| double cR = 0.500 * r + -0.418688 * g + -0.081312 * b; | |
| bool isFire = false; | |
| if(y >= cR && cR >= cB) | |
| { | |
| double crcb = cR - cB; | |
| double ycb = y - cB; | |
| if (!((crcb >= -0.1 && ycb >= -0.1 && ycb <= 0.3) || (crcb >= 0 && crcb <= 0.4 && ycb >= 0 && ycb <= 0.8))) | |
| isFire = true; | |
| } | |
| if (isFire) | |
| isFire = !(cR - cB > -0.1 && y - cB > -0.1 && y - cB <= 0.6); | |
| if (isFire) | |
| newImage[Y, X] = originalImage[Y, X]; | |
| else | |
| newImage[Y, X] = new Bgr(0, 0, 0); | |
| } | |
| } | |
| return newImage; | |
| } | |
| private void chkDetect_CheckedChanged(object sender, EventArgs e) | |
| { | |
| detectFire = chkDetect.Checked; | |
| } | |
| private void trbSeek_Scroll(object sender, EventArgs e) | |
| { | |
| int frameIndex = trbSeek.Value; | |
| videoCapture.SetCaptureProperty(CapProp.PosFrames, frameIndex); | |
| } | |
| private void chkFrameSkip_CheckedChanged(object sender, EventArgs e) | |
| { | |
| frameSkip = chkFrameSkip.Checked; | |
| } | |
| private void btnCamera_Click(object sender, EventArgs e) | |
| { | |
| OpenCamera(); | |
| } | |
| private void btnVideo_Click(object sender, EventArgs e) | |
| { | |
| OpenFileDialog dialog = new OpenFileDialog(); | |
| DialogResult result = dialog.ShowDialog(); | |
| if(result.Equals(DialogResult.OK)) | |
| if(dialog.FileName != null) | |
| OpenVideo(dialog.FileName); | |
| } | |
| } | |
| } |

SpaceApps is a NASA incubator innovation program.