Files
qrcode/qrCamera/Program.cs
T
2026-08-12 18:12:30 +02:00

301 lines
9.8 KiB
C#

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 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);
camera.Set(VideoCaptureProperties.Fps, 24);
if(Directory.Exists("cache"))
{
Directory.Delete("cache",true);
}
Directory.CreateDirectory("cache");
Mat hey = new Mat("photo.png");
Mat[] Cached = new Mat[10];
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);
int photocount = 0;
Mat src = Cv2.ImRead("test.png");
string[] files = new string[10];
int files_index =0;
while (true)
{
// if (!camera.Read(frame) || frame.Empty())
// {
// Console.Error.WriteLine("Nie udało się odczytać klatki");
// break;
// }
camera.Read(frame);
Result result = GetResult(frame);
if (result != null)
{
List<ResultPoint> 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]);
// Cv2.Circle(frame, (int)pos1[0], (int)pos1[1], 5, Scalar.Red, 2);
// Cv2.Circle(frame, (int)pos2[0], (int)pos2[1], 5, Scalar.Green, 2);
// Cv2.Circle(frame, (int)pos3[0], (int)pos3[1], 5, Scalar.Blue, 2);
PointF[] location;
try
{
location = Calculate(pos1, pos2, pos3, new float[2] { points[3].X, points[3].Y });
}
catch
{
continue;
}
// Mat roi = frame[new Rect((int)pos3[0],(int)pos3[1], src.Width+3, src.Height)];
Mat roi = frame[new Rect((int)pos3[0], (int)pos3[1], width,heigh)];
src.CopyTo(roi);
// Console.WriteLine($"szerokość:{width}");
// Console.WriteLine($"wysokosc:{heigh}");
// Console.WriteLine($"x:{pos3[0]}");
// Console.WriteLine($"y:{pos3[1]}");
// DrawLine(location); //draw red squre
var points1 = new List<OpenCvSharp.Point>
{
GetPoint(location[0]),
GetPoint(location[1]),
GetPoint(location[3]),
GetPoint(location[2])
};
// Zagnieźdź w dodatkową kolekcję:
IEnumerable<IEnumerable<OpenCvSharp.Point>> contours = new[] { points1 };
// Cv2.FillPoly(frame, contours, Scalar.White); // fill with white
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
{
// try
// {
int toload = files.IndexOf(result.Text);
Mat roi2 = frame[new Rect((int)pos3[0], (int)pos3[1], Cached[toload].Width, Cached[toload].Height)];
Cached[toload].CopyTo(roi2);
// Console.WriteLine("work");
// }
// catch { }
}
// Cv2.draw
// Cv2.Circle(frame, (int)(RightBottomX), (int)(RightBottomY), 5, Scalar.Green, 2);
//Cv2.Rectangle(frame, new Point((int)X, (int)Y), new Point ((int)Width, (int)Height), Scalar.Red, 2);
// Console.WriteLine(result.Text);
}
// frame.SaveImage($"photos/photo_{photocount}.png");
// photocount++;
Cv2.ImShow("Camera preview", frame);
Thread.Sleep(1000 / 24);
// Console.WriteLine("tick");
int key = Cv2.WaitKey(1);
if (key == 27 || key == 'q')
break;
}
Cv2.DestroyAllWindows();
}
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 GetResult(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)
);
}
}
}