本文记录一下使用OpenCVSharp包进行图像处理。包括使用两种方法增强图像对比度、缩放图像、删除透明像素功能。
该方法处理速度较慢,但是思路简单,逻辑清晰。
///
/// 增强图像对比度
///
/// 图像路径
public void EnhanceImageContrast(string path)
{
//读入的图像是RGB 但是像素顺序是BGR
using (Mat src = Cv2.ImRead(path, ImreadModes.AnyColor | ImreadModes.AnyDepth))
using (Mat dst = new Mat(src.Size(), src.Type())) //修改之后的图像
{
int height = src.Rows;
int width = src.Cols;
int cn = src.Channels(); //通道数
float alpha = 1.6f; //系数 alpha值越大,像素之间的差值越大,对比度越强烈
float beta = 0f; //增益 beta值是用于提高图片亮度增益值
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
if (cn == 1)
{
float color = src.At<float>(row, col);
dst.Set<float>(row, col, color);
}
else if (cn == 3)
{
Vec3b color = new Vec3b
{
Item0 = (byte)ControlPixelExtend((int)Math.Ceiling((src.At<Vec3b>(row, col).Item0) * alpha + beta)), //B
Item1 = (byte)ControlPixelExtend((int)Math.Ceiling((src.At<Vec3b>(row, col).Item1) * alpha + beta)), //G
Item2 = (byte)ControlPixelExtend((int)Math.Ceiling((src.At<Vec3b>(row, col).Item2) * alpha + beta)) //R
};
dst.Set<Vec3b>(row, col, color);
}
}
}
//参数:1 要保存图片的路径 2:图像的矩阵容器 ,(图片保存格式个根据自定义的后缀名)
//Cv2.ImWrite(@"C:\Users\deng\Desktop\ExportImages\out.png", dst);
using (new Window("dst Image", WindowMode.Normal, dst))
using (new Window("src Image", WindowMode.Normal, src))
{
Cv2.WaitKey(0);
}
}
}
该方法处理速度较快。
///
/// 使用指针快速操作像素,并增强图像对比度
///
/// 原图像路径
public Mat EnhanceContrastByPointer(string path)
{
Mat srcImg = Cv2.ImRead(path, ImreadModes.AnyColor | ImreadModes.AnyDepth);
Mat dstImg = srcImg.Clone();
//指针方法修改像素值
unsafe
{
float alpha = 2f; //系数 alpha值越大,像素之间的差值越大,对比度越强烈
float beta = 1f; //增益 beta值是用于提高图片亮度增益值
for (int i = 0; i < dstImg.Rows; i++)
{
IntPtr ptrColor = dstImg.Ptr(i);
for (int j = 0; j < dstImg.Cols; j++)
{
byte* pointerColor = (byte*)ptrColor.ToPointer(); //指针
//pointerColor是字节,一个像素值由三个字节存储
pointerColor[j * 3] = (byte)ControlPixelExtend((int)Math.Ceiling(pointerColor[j * 3] * alpha + beta)); //R
pointerColor[j * 3 + 1] = (byte)ControlPixelExtend((int)Math.Ceiling(pointerColor[j * 3 + 1] * alpha + beta)); //G
pointerColor[j * 3 + 2] = (byte)ControlPixelExtend((int)Math.Ceiling(pointerColor[j * 3 + 2] * alpha + beta)); //B
}
}
}
return dstImg;
}
///
/// 缩放图像
///
/// 原图像路径
public void PictureResize(Mat srcImg)
{
//函数原型:public Mat Resize(Size dsize, double fx = 0, double fy = 0, InterpolationFlags interpolation = InterpolationFlags.Linear);
//dsize:缩放之后的图像大小
//fx:宽度缩放比例
//fy:高度缩放比例
//interpolation:插值方式
//注意:缩放图像时,如果dsize中width或者height有一个为0,则使用fx与fy为缩放比例,否则使用dsize为最终缩放图像大小
//Mat Zoomout = src.Resize(new Size(src.Width/2, src.Height / 2),0,0,InterpolationFlags.Linear);//缩小
//Mat Zoomout = src.Resize(new Size(0, 0), 0.5, 0.5, InterpolationFlags.Linear);//缩小 与上一行效果相同
//Mat Zoomin = src.Resize(new Size(src.Width*1.2, src.Height*1.2), 0, 0, InterpolationFlags.Linear);//放大
Mat Zoomin = srcImg.Resize(new OpenCvSharp.Size(0, 0), 1.05, 0.98, InterpolationFlags.Linear);//放大 与上一行效果相同
//Cv2.ImShow("src image", src);
//Cv2.ImShow("Zoomout", Zoomout);
//Cv2.ImShow("Zoomin", Zoomin);
Cv2.ImWrite(@"C:\Users\deng\Desktop\ExportImages\res11.png", Zoomin);
}
该方法速度较慢。
///
/// 删除透明像素
///
/// 待删除透明像素的bitmap
/// 已删除透明像素的bitmap
public Bitmap DeleteTransparentPixel(Bitmap bitmap)
{
int y = 0; //非透明图像的高度
bool isFirstTransparentPixel = true;
Color[,] opaquePixel = new Color[bitmap.Width, bitmap.Height];
for (int i = 0; i < bitmap.Width; i++)
{
for (int j = 0; j < bitmap.Height; j++)
{
Color c = bitmap.GetPixel(i, j);
if (c.A != 0) //如果不是透明像素
opaquePixel[i, j] = c;
else
{
if (isFirstTransparentPixel) //如果第一次出现透明像素
{
y = j; //记录不透明像素的总行数
isFirstTransparentPixel = false;
break;
}
}
}
}
Bitmap b = new Bitmap(bitmap.Width, y);
for (int i = 0; i < b.Width; i++)
{
for (int j = 0; j < b.Height; j++)
{
b.SetPixel(i, j, opaquePixel[i, j]);
}
}
return b;
}
1.c#OpenCVSharp指针快速读取像素:https://mp.weixin.qq.com/s/5DStN-5ONEO-OFZ9v0HDUw
2.OpenCvSharp图像亮度和对比度调整(速度较慢):https://blog.csdn.net/weixin_41049188/article/details/90612010
3.OpenCVSharp图像缩放与插值:https://blog.csdn.net/CAI____NIAO/article/details/121571283