using OpenCvSharp; using ZXing; using ZXing.QrCode; using OpenCvSharp.Extensions; using ZXing.Windows.Compatibility; using ZXing.Common; using System.Runtime.InteropServices; using System.Drawing; using System.Net; using System.Runtime.InteropServices.Marshalling; using Emgu.CV.Face; // using Emgu.CV.CvEnum; namespace BarcodeReaderExample { class Program { static void Main(string[] args) { VideoCapture camera = new VideoCapture("/dev/video0", VideoCaptureAPIs.V4L2); if (!camera.IsOpened()) throw new Exception("Nie można otworzyć kamery /dev/video0"); camera.Set(VideoCaptureProperties.FrameWidth, 1280); camera.Set(VideoCaptureProperties.FrameHeight, 720); int fps = 60; int avalibeImages = 20; camera.Set(VideoCaptureProperties.Fps, fps); if (Directory.Exists("cache")) { Directory.Delete("cache", true); } Directory.CreateDirectory("cache"); Mat hey = new Mat("photo.png"); Mat[] Cached = new Mat[avalibeImages]; int imgX = 0; int imgY = 0; using var rgb = new Mat(); // OpenCV stores camera frames as BGR. // ZXing's RGBLuminanceSource expects RGB. // Cv2.CvtColor(frame, rgb, ColorConversionCodes.BGR2RGB); Cv2.NamedWindow("Camera preview", WindowFlags.AutoSize); // Mat src = Cv2.ImRead("test.png"); int whenWasLastTimeQrDetected = 0; Mat Lastimage = new Mat(); IEnumerable> contours = null; // PointF[] location; string[] files = new string[avalibeImages]; int files_index = 0; while (true) { camera.Read(frame); Result result = ReadQrCode(frame); // Console.WriteLine(Lastimage.Empty()); if (!(Lastimage.Empty())) { Mat roi2 = frame[new Rect(0, 0, Lastimage.Width, Lastimage.Height)]; Lastimage.CopyTo(roi2); } if (result != null) { whenWasLastTimeQrDetected = 5; List points = result.ResultPoints.ToList(); float[] pos1 = new float[2] { points[0].X, points[0].Y }; /// lewy dolny róg float[] pos2 = new float[2] { points[2].X, points[2].Y }; ///prawy górny róg float[] pos3 = new float[2] { points[1].X, points[1].Y }; ///lewy górny róg int width = (int)(pos2[0] - pos3[0]); int heigh = (int)(pos1[1] - pos3[1]); PointF[] location; try { location = Calculate(pos1, pos2, pos3, new float[2] { points[3].X, points[3].Y }); } catch { continue; } var points1 = new List { GetPoint(location[0]), GetPoint(location[1]), GetPoint(location[3]), GetPoint(location[2]) }; int qrWidth = GetPoint(location[1]).X - GetPoint(location[0]).X; int qrHeigh = GetPoint(location[2]).Y - GetPoint(location[0]).Y; imgX = GetPoint(location[0]).X; imgY = GetPoint(location[0]).Y; contours = new[] { points1 }; Cv2.FillPoly(frame, contours, Scalar.White); // fill with white //Write Text // Cv2.PutText(frame, result.Text, new OpenCvSharp.Point((int)(pos2[0]-pos3[0])/2+(int)pos3[0]-160, (int)(pos2[1]-pos3[1])/2+(int)pos3[1]+60), HersheyFonts.HersheySimplex, 0.8, Scalar.Black, 2); if (!files.Contains(result.Text)) { files[files_index] = result.Text; Console.WriteLine("downloading: " + result.Text); using (var client = new WebClient()) { client.DownloadFile(result.Text, "cache/" + files_index + ".png"); // Thread.Sleep(2000); } Cached[files_index] = new Mat("cache/" + files_index + ".png"); files_index++; } else { int toload = files.IndexOf(result.Text); Mat toDraw= new Mat(); InputArray inputArray = toDraw; // Console.WriteLine($"{qrWidth} , {qrHeigh}"); try { Cv2.Resize(Cached[toload],toDraw,new OpenCvSharp.Size(qrWidth,qrHeigh)); } catch {continue;} Lastimage = toDraw; // toDraw.Resize(1,3); try { Mat roi2 = frame[new Rect(GetPoint(location[0]).X, GetPoint(location[0]).Y, toDraw.Width, toDraw.Height)]; toDraw.CopyTo(roi2); } catch{} } } else if (whenWasLastTimeQrDetected > 0) { Cv2.FillPoly(frame, contours, Scalar.White); // fill with white try { Mat roi2 = frame[new Rect(imgX, imgY, Lastimage.Width, Lastimage.Height)]; Lastimage.CopyTo(roi2); } catch{} whenWasLastTimeQrDetected--; } Cv2.ImShow("Camera preview", frame); Thread.Sleep(1000 / fps); int key = Cv2.WaitKey(1); if (key == 27 || key == 'q') break; } Cv2.DestroyAllWindows(); } static void rotate() { } static OpenCvSharp.Point GetPoint(PointF pointf) { return new OpenCvSharp.Point(pointf.X, pointf.Y); } static PointF[] Calculate(float[] pos1, float[] pos2, float[] pos3, float[] pos4) { // Your 4 detected points (change the names if needed) PointF p1 = new PointF(pos1[0], pos1[1]); PointF p2 = new PointF(pos2[0], pos2[1]); PointF p3 = new PointF(pos3[0], pos3[1]); PointF p4 = new PointF(pos4[0], pos4[1]); // 1. Find the center of the QR float centerX = (p1.X + p2.X + p3.X + p4.X) / 4f; float centerY = (p1.Y + p2.Y + p3.Y + p4.Y) / 4f; PointF center = new PointF(centerX, centerY); // 2. How much bigger you want the box (1.0 = exact size, 1.15 = 15% bigger) float scale = 1.35f; // ← change this value // 3. Move every corner away from the center PointF Expand(PointF p) { float dx = p.X - center.X; float dy = p.Y - center.Y; return new PointF(center.X + dx * scale, center.Y + dy * scale); } float scaleLB = 1.75f; // ← change this value PointF ExpandLB(PointF p) { float dx = p.X - center.X; float dy = p.Y - center.Y; return new PointF(center.X + dx * scaleLB, center.Y + dy * scaleLB); } PointF topLeft = Expand(p3); // change order if needed PointF topRight = Expand(p2); PointF bottomRight = ExpandLB(p4); PointF bottomLeft = Expand(p1); PointF[] Location = new PointF[] { topLeft, topRight, bottomLeft, bottomRight }; return Location; // 4. Now draw the 4 lines // Example with System.Drawing or Unity or whatever you use: } static void DrawLine(PointF p1, PointF p2) { Cv2.Line(frame, (int)p1.X, (int)p1.Y, (int)p2.X, (int)p2.Y, Scalar.Red, 2); } static void DrawLine(PointF[] Location) { DrawLine(Location[0], Location[1]); DrawLine(Location[1], Location[2]); DrawLine(Location[2], Location[3]); DrawLine(Location[3], Location[0]); } static void DrawLine(float x1, float y1, float x2, float y2) { Cv2.Line(frame, (int)x1, (int)y1, (int)x2, (int)y2, Scalar.Red, 2); } static Mat frame = new Mat(); static Result ReadQrCode(Mat frame) { QRCodeReader reader = new QRCodeReader(); Result result = reader.decode(MatToBinaryBitmap(frame)); return result; } static BinaryBitmap MatToBinaryBitmap(Mat frame) { if (frame.Empty()) throw new ArgumentException("The Mat is empty.", nameof(frame)); using var rgb = new Mat(); // OpenCV uses BGR; ZXing RGBLuminanceSource expects RGB. Cv2.CvtColor( frame, rgb, ColorConversionCodes.BGR2RGB ); // Clone ensures contiguous pixel memory. using var contiguous = rgb.Clone(); int width = contiguous.Width; int height = contiguous.Height; int byteCount = checked( (int)(contiguous.Total() * contiguous.ElemSize()) ); byte[] pixels = new byte[byteCount]; Marshal.Copy( contiguous.Data, pixels, 0, pixels.Length ); var luminanceSource = new RGBLuminanceSource( pixels, width, height, RGBLuminanceSource.BitmapFormat.RGB24 ); return new BinaryBitmap( new HybridBinarizer(luminanceSource) ); } } }