long candy ready to test
This commit is contained in:
124
Hawkeye.VisionBuilder.UI.Sources.Hawkeye/OpenCVBayerFilter.cs
Normal file
124
Hawkeye.VisionBuilder.UI.Sources.Hawkeye/OpenCVBayerFilter.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using NLog.Filters;
|
||||
using OpenCvSharp;
|
||||
|
||||
namespace Hawkeye.VisionBuilder.UI.Sources.Hawkeye;
|
||||
|
||||
public class OpenCVBayerProcessor
|
||||
{
|
||||
private SplineInterpolator GreenInterpolation { get; set; }
|
||||
private SplineInterpolator RedInterpolation { get; set; }
|
||||
private SplineInterpolator BlueInterpolation { get; set; }
|
||||
|
||||
// Cached lookup tables
|
||||
private byte[] redLut;
|
||||
private byte[] greenLut;
|
||||
private byte[] blueLut;
|
||||
private Mat _lookupTable;
|
||||
|
||||
public OpenCVBayerProcessor()
|
||||
{
|
||||
// Initialize with default linear interpolation (same as your defaults)
|
||||
GreenInterpolation = new SplineInterpolator(new Dictionary<double, double>()
|
||||
{{0,0}, { 100, 100 }, { 255,255}});
|
||||
RedInterpolation = new SplineInterpolator(new Dictionary<double, double>()
|
||||
{{0,0}, { 100, 100 }, { 255,255}});
|
||||
BlueInterpolation = new SplineInterpolator(new Dictionary<double, double>()
|
||||
{{0,0}, { 100, 100 }, { 255,255}});
|
||||
|
||||
UpdateLookupTables();
|
||||
}
|
||||
|
||||
public void SetInterpolators(SplineInterpolator red, SplineInterpolator green, SplineInterpolator blue)
|
||||
{
|
||||
RedInterpolation = red;
|
||||
GreenInterpolation = green;
|
||||
BlueInterpolation = blue;
|
||||
UpdateLookupTables();
|
||||
}
|
||||
|
||||
public void SetCalibration(List<Dictionary<double, double>> calibration)
|
||||
{
|
||||
RedInterpolation = new SplineInterpolator(calibration[0]);
|
||||
GreenInterpolation = new SplineInterpolator(calibration[1]);
|
||||
BlueInterpolation = new SplineInterpolator(calibration[2]);
|
||||
UpdateLookupTables();
|
||||
}
|
||||
|
||||
private void UpdateLookupTables()
|
||||
{
|
||||
redLut = Enumerable.Range(0, 256).Select(x => (byte)RedInterpolation.GetValue(x)).ToArray();
|
||||
greenLut = Enumerable.Range(0, 256).Select(x => (byte)GreenInterpolation.GetValue(x)).ToArray();
|
||||
blueLut = Enumerable.Range(0, 256).Select(x => (byte)BlueInterpolation.GetValue(x)).ToArray();
|
||||
|
||||
// Create lookup table for all three channels
|
||||
_lookupTable = new Mat(1, 256, MatType.CV_8UC3);
|
||||
|
||||
// Use the Mat indexer for safe access
|
||||
var indexer = _lookupTable.GetGenericIndexer<Vec3b>();
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
indexer[0, i] = new Vec3b(blueLut[i], greenLut[i], redLut[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public Mat ProcessBayerImage(Mat grayImage)
|
||||
{
|
||||
// Step 1: Apply Bayer demosaicing with RG pattern (matching your pattern)
|
||||
Mat colorImage = new Mat();
|
||||
Cv2.CvtColor(grayImage, colorImage, ColorConversionCodes.BayerBG2BGR);
|
||||
|
||||
// Step 2: Apply color interpolation/correction using lookup tables
|
||||
Mat correctedImage = ApplyColorCorrection(colorImage);
|
||||
|
||||
return correctedImage;
|
||||
}
|
||||
|
||||
private Mat ApplyColorCorrection(Mat colorImage)
|
||||
{
|
||||
|
||||
|
||||
// Apply the lookup table
|
||||
Mat result = new Mat();
|
||||
Cv2.LUT(colorImage, _lookupTable, result);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Alternative: Apply correction per channel if you need more control
|
||||
public Mat ProcessBayerImageWithChannelControl(Mat grayImage)
|
||||
{
|
||||
// Step 1: Demosaic
|
||||
Mat colorImage = new Mat();
|
||||
Cv2.CvtColor(grayImage, colorImage, ColorConversionCodes.BayerBG2BGR);
|
||||
|
||||
// Step 2: Split channels
|
||||
Mat[] channels = Cv2.Split(colorImage);
|
||||
|
||||
// Step 3: Apply individual LUTs to each channel
|
||||
Mat blueCorrected = new Mat();
|
||||
Mat greenCorrected = new Mat();
|
||||
Mat redCorrected = new Mat();
|
||||
|
||||
Mat blueLutMat = new Mat(1, 256, MatType.CV_8U, blueLut);
|
||||
Mat greenLutMat = new Mat(1, 256, MatType.CV_8U, greenLut);
|
||||
Mat redLutMat = new Mat(1, 256, MatType.CV_8U, redLut);
|
||||
|
||||
Cv2.LUT(channels[0], blueLutMat, blueCorrected);
|
||||
Cv2.LUT(channels[1], greenLutMat, greenCorrected);
|
||||
Cv2.LUT(channels[2], redLutMat, redCorrected);
|
||||
|
||||
// Step 4: Merge channels back
|
||||
Mat result = new Mat();
|
||||
Cv2.Merge(new Mat[] { blueCorrected, greenCorrected, redCorrected }, result);
|
||||
|
||||
// Cleanup
|
||||
foreach (var channel in channels) channel.Dispose();
|
||||
blueCorrected.Dispose();
|
||||
greenCorrected.Dispose();
|
||||
redCorrected.Dispose();
|
||||
colorImage.Dispose();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user