private Mat Recipe(string path, double value, string option) { if (path != null) { Mat orgMat = new Mat(path); Mat previewMat = new Mat(); #region //Algorithm Mat matrix = new Mat(); switch (option) { case "Contrast": Cv2.AddWeighted(orgMat, value, orgMat, 0, 0, previewMat); break; //AddWeighted 함수를 이용해서 gamma 인자를 통해 가중치의 합에 추가적인 덧셈을 한꺼번에 수행 할 수 있다. //computes weighted sum of two arrays (dst = alpha*src1 + beta*src2 + gamma) //http://suyeongpark.me/archives/tag/opencv/page/2 case "Brightness": Cv2.Add(orgMat, value, previewMat); break; //Add 함수를 이용해서 영상의 덧셈을 수행 한다. //Add 연산에서는 자동으로 포화 연산을 수행한다. //http://suyeongpark.me/archives/tag/opencv/page/2 case "Blur": Cv2.GaussianBlur(orgMat, previewMat, new OpenCvSharp.Size(9, 9), value, 1, BorderTypes.Default); //GaussianBlur break; //영상이나 이미지를 흐림 효과를 주어 번지게 하기 위해 사용합니다. 해당 픽셀의 주변값들과 비교하고 계산하여 픽셀들의 색상 값을 재조정합니다. //각 필세마다 주변의 픽셀들의 값을 비교하고 계산하여 픽섹들의 값을 재조정 하게 됩니다. 단순 블러의 경우 파란 사격형 안에 평균값으로 //붉은색 값을 재종하게 되고, 모든 픽셀들에 대하여 적용을 하게 된다. //https://076923.github.io/posts/C-opencv-13/ case "Rotation": matrix = Cv2.GetRotationMatrix2D(new Point2f(orgMat.Width / 2, orgMat.Height / 2), value, 1.0); // 2x3 회전 행렬 생성 함수 GetRotationMatrix2D Cv2.WarpAffine(orgMat, previewMat, matrix, new OpenCvSharp.Size(orgMat.Width, orgMat.Height), InterpolationFlags.Linear, BorderTypes.Replicate); break; //WarpAffine(원본 배열, 결과 배열, 행렬, 결과 배열의 크기) 결과 배열의 크기를 설정하는 이유는 회전 후, 원본 배열의 이미지 크기와 다를 수 있기 때문이다. //Interpolation.Linear은 영상이나 이미지 보간을 위해 보편적으로 사용되는 보간법이다. //BoderTypes.Replicate 여백을 검은색으로 채우면서 회전이 되더라도 zeropadding 된다. //https://076923.github.io/posts/C-opencv-6/ case "Rotation90": matrix = Cv2.GetRotationMatrix2D(new Point2f(orgMat.Width / 2, orgMat.Height / 2), 90, 1.0); Cv2.WarpAffine(orgMat, previewMat, matrix, new OpenCvSharp.Size(orgMat.Width, orgMat.Height), InterpolationFlags.Linear, BorderTypes.Reflect); break; //WarpAffine(원본 배열, 결과 배열, 행렬, 결과 배열의 크기) 결과 배열의 크기를 설정하는 이유는 회전 후, 원본 배열의 이미지 크기와 다를 수 있기 때문이다. //Interpolation.Linear은 영상이나 이미지 보간을 위해 보편적으로 사용되는 보간법이다. //BoderTypes.Replicate 여백을 검은색으로 채우면서 회전이 되더라도 zeropadding 된다. //https://076923.github.io/posts/C-opencv-6/ case "Horizontal Flip": Cv2.Flip(orgMat, previewMat, FlipMode.Y); break; //Flip(원본 이미지, 결과 이미지, 대칭 축 색상 공간을 변환), 대칭 축(FlipMode)를 사용하여 대칭 진행 //https://076923.github.io/posts/C-opencv-5/ case "Vertical Flip": Cv2.Flip(orgMat, previewMat, FlipMode.X); break; //Flip(원본 이미지, 결과 이미지, 대칭 축 색상 공간을 변환), 대칭 축(FlipMode)를 사용하여 대칭 진행 //https://076923.github.io/posts/C-opencv-5/ case "Noise": matrix = new Mat(orgMat.Size(), MatType.CV_8UC3); Cv2.Randn(matrix, Scalar.All(0), Scalar.All(value)); Cv2.AddWeighted(orgMat, 1, matrix, 1, 0, previewMat); break; //Randn 정규 분포를 나타내는 이미지를 랜덤하게 생성하는 방법 //AddWeighted 두 이미지를 가중치를 설정하여 합치면서 진행 // case "Zoom In": //#1. Center만 확대 double width_param = (int)(0.8 * orgMat.Width); // 0.8이 배율 orgMat.Width이 원본이미지의 사이즈 // 나중에 0.8만 80%형식으로 바꿔서 파라미터로 빼야됨 double height_param = (int)(0.8 * orgMat.Height); // 0.8이 배율 orgMat.Height 원본이미지의 사이즈 // int startX = orgMat.Width - (int)width_param; // 이미지를 Crop해올 좌상단 위치 지정하는값 // 원본사이즈 - 배율로 감소한 사이즈 int startY = orgMat.Height - (int)height_param; // Mat tempMat = new Mat(orgMat, new OpenCvSharp.Rect(startX, startY, (int)width_param - (int)(0.2 * orgMat.Width), (int)height_param - (int)(0.2 * orgMat.Height))); //중간과정 mat이고 Rect안에 x,y,width,height 값 지정해주는거 //예외처리 범위 밖으로 벗어나는경우 shift시키거나 , 제로페딩을 시키거나 //예외처리 Cv2.Resize(tempMat, previewMat, new OpenCvSharp.Size(orgMat.Width, orgMat.Height), (double)((double)orgMat.Width / (double)(width_param - (int)(0.2 * orgMat.Width))), (double)((double)orgMat.Height / ((double)(height_param - (int)(0.2 * orgMat.Height)))), InterpolationFlags.Cubic); // (double) ( (double)orgMat.Width / (double)width_param) // 형변환 원본이미지 형변환 / 타겟이미지 배율 == 타겟이미지가 원본이미지 대비 몇배인가? 의 수식임 // (double) ( (double)orgMat.Height / (double)height_param) break; case "Sharpen": float filterBase = -1f; float filterCenter = filterBase * -9; float[] data = new float[9] { filterBase, filterBase, filterBase, filterBase, filterCenter, filterBase, filterBase, filterBase, filterBase }; Mat kernel = new Mat(3, 3, MatType.CV_32F, data); Cv2.Filter2D(orgMat, previewMat, orgMat.Type(), kernel); break; // // // // Contrast Limited Adapative Histogram Equalization case "CLAHE": CLAHE test = Cv2.CreateCLAHE(); test.SetClipLimit(10.0f); if (value < 1) { value = 1; } test.SetTilesGridSize(new OpenCvSharp.Size(value, value)); Mat normalized = new Mat(); Mat temp = new Mat(); Cv2.CvtColor(orgMat, orgMat, ColorConversionCodes.RGB2HSV); var splitedMat = orgMat.Split(); test.Apply(splitedMat[2], splitedMat[2]); Cv2.Merge(splitedMat, previewMat); Cv2.CvtColor(previewMat, previewMat, ColorConversionCodes.HSV2RGB); break; // // // default: break; } matrix.Dispose(); //이미지의 메모리 할당을 해제 합니다. orgMat.Dispose(); //이미지의 메모리 할당을 해제 합니다. return(previewMat); #endregion } return(null); }
/// <summary> /// Analyze video frame /// </summary> private void AnalyzeVideo() { var newImage = new Mat(); var newFrame = new CFrame(); newFrame = cframe; newImage = newFrame.Frame; newImage = newImage.CvtColor(ColorConversionCodes.BGR2GRAY); Utilities.debugmessage("Clahe: " + Cv2.Mean(newImage)[0]); clhLight.SetClipLimit(2); clhLight.Apply(newImage, newImage); var st = new Stopwatch(); Utilities.debugmessage("Clahe: " + Cv2.Mean(newImage)[0]); st.Start(); List <YoloItem> items = yoloWrapper.Detect(newImage.Resize(new OpenCvSharp.Size(w, h)).ToBytes()).ToList(); var coeffW = ((float)newImage.Width / w); var coeffH = ((float)newImage.Height / h); foreach (var itm in items) { if (itm.Confidence < 0.66) { break; } if (itm.Type == "dcoup") { // Logging, Tracking TimeSpan curTime = TimeSpan.FromMilliseconds(newFrame.frameNum * frameTime); string[] _toAdd = { newFrame.frameNum.ToString(), (itm.X * coeffW).ToString(), (itm.Y * coeffH).ToString(), ((itm.X * coeffW) + (itm.Width * coeffH)).ToString(), ((itm.Y * coeffH) + (itm.Height * coeffW)).ToString(), curTime.ToString(@"hh\:mm\:ss") }; Log(_toAdd); //if (myConnection.State == System.Data.ConnectionState.Open) //{ // try // { // dataBaseLog(_toAdd); // } // catch { } //} ListViewItem item1 = new ListViewItem(newFrame.frameNum.ToString(), 0); item1.SubItems.Add((itm.X * coeffW).ToString()); item1.SubItems.Add((itm.Y * coeffH).ToString()); item1.SubItems.Add((itm.Width * coeffW + (itm.X * coeffW)).ToString()); item1.SubItems.Add((itm.Height * coeffH + (itm.Y * coeffH)).ToString()); item1.SubItems.Add(curTime.ToString(@"hh\:mm\:ss")); window.listView1.BeginInvoke(new Action(() => { window.listView1.Items.AddRange(new ListViewItem[] { item1 }); })); // Tracking algorithm // Speed limit ~80 KM/h (if lenght between coups is 12-15 meters) if (((newFrame.frameNum * frameTime) > (checkTime + 650)) && Math.Abs((float)masTrackDcoup * coeffW - (float)itm.X * coeffW) < 30) { checkTime = (newFrame.frameNum * frameTime); masTrackDcoup = itm.X; } else if (((newFrame.frameNum * frameTime) > (checkTime + 650))) { CoupCount++; checkTime = (newFrame.frameNum * frameTime); masTrackDcoup = itm.X; } else if (CoupCount == 0) { CoupCount++; checkTime = (newFrame.frameNum * frameTime); masTrackDcoup = itm.X; } else { checkTime = (newFrame.frameNum * frameTime); masTrackDcoup = itm.X; } } } st.Stop(); window.toolStripTimer.Text = "Elapsed time: " + st.ElapsedMilliseconds + " ms"; window.toolStripCounter.Text = "Count: " + CoupCount; // Drawing new frame in picBox window.picBox.BeginInvoke(new Action(() => { window.picBox.ImageIpl = newImage.Resize(new OpenCvSharp.Size(window.picBox.Width, window.picBox.Height)); window.picBox.setRect(items); })); if (cframe.frameNum + 1 > frameCnt) { PLAY_FLAG = false; window.Invoke(new Action(() => { window.pauseButton.Enabled = false; window.btn_Detect.Enabled = true; })); } analyzeStarted = false; }