OpenCVForUnity二值化和灰度化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mseol/article/details/79257964

随着csdn博客系统升级,尝试使用md写文章,感觉还不错。继续使用OpenCVForUnity处理图片,今次的效果是灰度化和二值化,当所有功能实现后,可能会做出一个unity版的美图秀秀。

首先我们来确定一下两者的概念。

  • 二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。
  • 灰度化,在RGB模型中,如果R=G=B时,则彩色表示一种灰度颜色,其中R=G=B的值叫灰度值,因此,灰度图像每个像素只需一个字节存放灰度值(又称强度值、亮度值),灰度范围为0-255。

什么,没看懂?那看一下这张图吧,解释了什么叫做“有一张好图,就可以什么也不用解释了”。
lena

构建一个简单的场景

很明显,灰度图的取值范围比二值图大,那么我们就先生成灰度图,再通过将灰度值设置为0或255生成二值图。
这里写图片描述

  • 创建一个空场景,使用ugui摆好一个RawImage(或Image),和两个按钮。
  • 创建一个Binaryzation类。Awake()中注册RawImage的约束比例,和2个按钮的点击方法,这里我先把二值化按钮交互关闭,灰度化处理后再激活。
[SerializeField] private RawImage targetImage;
[SerializeField] private Button grayButton;
[SerializeField] private Button binaryButton;
private AspectRatioFitter aspectRatioFitter;

void Awake()
{
    aspectRatioFitter = targetImage.GetComponent<AspectRatioFitter>();
    grayButton.onClick.AddListener(OnGray);
    binaryButton.interactable = false;
    binaryButton.onClick.AddListener(OnBinary);
}
  • Start()中读取一张本地图片,并在RawImage上显示这张图片。注意这里使用Imgcodecs.imread()这个API从本地读取图片,需要在读取后做一些列通道转换。
private Mat srcMat, dstMat;

void Start()
{
    srcMat = Imgcodecs.imread(Application.dataPath + "/Textures/kizuna.jpg", 1);

    List<Mat> channels = new List<Mat>();
    Core.split(srcMat, channels);
    Mat imageRed = new Mat();
    imageRed = channels[0];
    Mat imageGreen = new Mat();
    imageGreen = channels[1];
    Mat imageBlue = new Mat();
    imageBlue = channels[2];
    channels[0] = channels[2];
    channels[2] = imageRed;
    Mat mergeImage = new Mat();
    Core.merge(channels, srcMat);

    aspectRatioFitter.aspectRatio = (float)srcMat.width() / (float)srcMat.height();

    Texture2D t2d = new Texture2D(srcMat.width(), srcMat.height());
    Utils.matToTexture2D(srcMat, t2d);
    targetImage.texture = t2d;
}
  • 使用Imgproc.cvtColor()方法将之前读取的Mat转为灰度。代码里也举例了一种简便的方法,在读取时直接转灰度,可省略转换步骤。然后把Mat转Texture2D,再显示到RawImage上,完成图像灰度化的效果。
void OnGray()
{
    binaryButton.interactable = true;

    //方法1.读取时就转为灰度
    //srcMat = Imgcodecs.imread(Application.dataPath + "/Textures/kizuna.jpg", 0); //flag=0,将读入的彩色图像直接以灰度图像读入
    //方法2.将现有Mat转为灰度
    Imgproc.cvtColor(srcMat, srcMat, Imgproc.COLOR_BGR2GRAY); // 转为灰度图像

    Texture2D t2d = new Texture2D(srcMat.width(), srcMat.height());
    Utils.matToTexture2D(srcMat, t2d);
    targetImage.texture = t2d;
}
  • 将灰度的Mat克隆一个副本,使用Imgproc.threshold()进行二值化处理,通过阈值(minThresh, maxThresh)调节取值范围。
private double minThresh = 200d; //0(黑)->255(白)
private double maxThresh = 250d;
void OnBinary()
{
    //克隆一个副本
    dstMat = srcMat.clone();
    //二值化处理
    Imgproc.threshold(srcMat, dstMat, minThresh, maxThresh, Imgproc.THRESH_BINARY_INV); //CV_THRESH_BINARY

    Texture2D t2d = new Texture2D(dstMat.width(), dstMat.height());
    Utils.matToTexture2D(dstMat, t2d);
    targetImage.texture = t2d;
}

最终效果

效果图

猜你喜欢

转载自blog.csdn.net/mseol/article/details/79257964