由于插件数据类型、API与c++版差异较大,这里需要花些功夫学习下Mat中像素的操作。细心的小朋友通过上一篇《锐化与模糊》中关于椒盐噪声的实现,可能已经学习到了具体的方法。
//用一个byte[]类型byteArray容器,从mat中取像素。
byte[] byteArray = new byte[dstMat.width() * dstMat.height()];
Utils.copyFromMat<byte>(dstMat, byteArray);
//可以通过id,控制到单通道中任意像素的值
byteArray[i + dstMat.width() * j] = 255;
//处理完的容器,拷贝回给mat,就是处理完的mat
Utils.copyToMat<byte>(byteArray, dstMat);
椒盐噪声中是对单通道(灰度图)随机添加白点,如果要处理RGB彩色图,需要先把通道单独拆出来处理像素,处理完再合并回去。
代码
[SerializeField] private Image m_showImage;
Mat srcMat;
List<Mat> channels;
byte[] byteArrayR, byteArrayG, byteArrayB;
void Start()
{
srcMat = Imgcodecs.imread(Application.dataPath + "/Textures/sample.jpg");
Imgproc.cvtColor(srcMat, srcMat, Imgproc.COLOR_BGR2RGB);
//Debug.Log(srcMat.channels()); //3
//提取通道
channels = new List<Mat>();
Core.split(srcMat, channels);
//byteArray = new byte[srcMat.width() * srcMat.height()];
byteArrayR = new byte[channels[0].width() * channels[0].height()];
byteArrayG = new byte[channels[0].width() * channels[0].height()];
byteArrayB = new byte[channels[0].width() * channels[0].height()];
Utils.copyFromMat<byte>(channels[0], byteArrayR);
Utils.copyFromMat<byte>(channels[1], byteArrayG);
Utils.copyFromMat<byte>(channels[2], byteArrayB);
//遍历像素
int width = srcMat.width();
int height = srcMat.height();
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
//反色操作
int rValue = 255 - byteArrayR[x + width * y];
byteArrayR[x + width * y] = (byte)rValue;
//Debug.Log(rValue); //r通道值
int gValue = 255 - byteArrayG[x + width * y];
byteArrayG[x + width * y] = (byte)gValue;
int bValue = 255 - byteArrayB[x + width * y];
byteArrayB[x + width * y] = (byte)bValue;
}
}
//拷贝回Mat
Utils.copyToMat(byteArrayR, channels[0]);
Utils.copyToMat(byteArrayG, channels[1]);
Utils.copyToMat(byteArrayB, channels[2]);
//合并通道
Core.merge(channels, srcMat);
//ugui显示
Texture2D t2d = new Texture2D(srcMat.width(), srcMat.height());
Sprite sp = Sprite.Create(t2d, new UnityEngine.Rect(0, 0, t2d.width, t2d.height), Vector2.zero);
m_showImage.sprite = sp;
Utils.matToTexture2D(srcMat, t2d);
}