LUTを使ってガンマ補正を行います。
ソースコード
ファイル名:Form1.cs(前回の記事のソースコードに追加)
// ガンマ補正(Form1のメンバーとして追加)
readonly ToolStripMenuItem gammaMenuItem = new()
{
Text = "ガンマ補正",
};
// ガンマ補正(Form1のコンストラクタに追加)
filterMenuItem.DropDownItems.Add(gammaMenuItem);
gammaMenuItem.Click += (s, e) =>
{
if (_buffBmp is null) return;
Bitmap? bmp = GammaDialog(_buffBmp);
if (bmp is not null)
{
this.Bmp = bmp;
mainPicbox.Image = this.Bmp;
}
};
ファイル名:Form1.Gamma.cs(新規追加)
using OpenCvSharp;
using OpenCvSharp.Extensions;
namespace GazouKakou01;
public partial class Form1 : Form
{
public static Bitmap? GammaDialog(Bitmap src)
{
const string filterName = "ガンマ補正";
Form frm = new Form
{
FormBorderStyle = FormBorderStyle.FixedDialog,
ClientSize = new System.Drawing.Size(640, 480),
Text = filterName,
};
Label lbl = new Label
{
Size = new System.Drawing.Size(600, 60),
Location = new System.Drawing.Point(10, 10),
Text = filterName,
};
lbl.Parent = frm;
PictureBox picbox = new()
{
Size = new System.Drawing.Size(600, 320),
Location = new System.Drawing.Point(10, 70),
Parent = frm,
};
Button okBtn = new Button
{
Size = new System.Drawing.Size(80,40),
Location = new System.Drawing.Point(10, 410),
Text = "OK",
DialogResult = DialogResult.OK,
};
okBtn.Parent = frm;
Button cancelBtn = new Button
{
Size = new System.Drawing.Size(80,40),
Location = new System.Drawing.Point(100, 410),
Text = "Cancel",
DialogResult = DialogResult.Cancel,
};
cancelBtn.Parent = frm;
frm.AcceptButton = okBtn;
frm.CancelButton = cancelBtn;
Label label1 = new()
{
Size = new System.Drawing.Size(120,40),
Location = new System.Drawing.Point(190, 410),
Parent = frm,
};
TrackBar track1 = new()
{
Minimum = 0,
Maximum = 100,
Value = 0,
TickFrequency = 1,
SmallChange = 1,
LargeChange = 10,
Size = new System.Drawing.Size(100,40),
Location = new System.Drawing.Point(320, 410),
Parent = frm,
};
// mat変換
var srcMat = BitmapConverter.ToMat(src);
// ガンマ補正
bool filterExecFlag = false;
Func<Mat, double, Mat> filter = new((src, gamma)=>
{
filterExecFlag = true;
Mat dst = new();
byte[] lut = new byte[256];
for(int i=0; i < lut.Length; i++)
{
if (gamma == 0.0d)
lut[i] = (byte)i;
else
lut[i] = (byte)(System.Math.Pow((double)(i / 255.0d), 1.0d / gamma) * 255.0d);
}
Cv2.LUT(src, lut, dst);
filterExecFlag = false;
return dst;
});
track1.ValueChanged += async (s, e) =>
{
Mat? dstMat = null;
double gamma = (double)track1.Value / 10.0d;
label1.Text = String.Format("ガンマ{0}", gamma);
if (filterExecFlag) return;
double backupValue;
do {
backupValue = gamma;
dstMat?.Dispose();
dstMat = await Task.Run(()=> filter(srcMat, gamma));
gamma = (double)track1.Value / 10.0d;
} while (backupValue != gamma);
picbox.Image?.Dispose();
picbox.Image = BitmapConverter.ToBitmap(dstMat);
dstMat?.Dispose();
};
frm.Load += (s, e) =>
{
track1.Value = 6;
};
if (frm.ShowDialog() == DialogResult.Cancel)
{
return null;
} else {
return (Bitmap)picbox.Image;
}
}
}
コメント