C# 使用OpenCV在一張圖片里尋找人臉


先上個效果圖

相關庫的下載

例程中用到一個庫叫做emgucv,是opencv\的net封裝
編譯打包好的穩定版,在這:https://sourceforge.net/projects/emgucv/files/emgucv/
如果要最新代碼,在這里獲取:https://github.com/emgucv/emgucv

建立工程

首先建立一個C#控制台工程.添加引用:Emgu.CV.World.dll
然后添加這2個文件到工程(在emgucv的壓縮包里有的,搜索下文件吧~):
注意:其中的dll文件需要根據要編譯的程序是32位還是64位選不同文件

記得把"復制到輸出目錄"設為"較新則復制"
另外准備一張要識別的圖片,放到編譯輸出目錄.
接下來就是編輯代碼了,后面所有代碼都在main里

配置OpenCV使用顯卡運算(如果支持的話)

使用顯卡處理圖像數據效率會很多,如果你的設備支持,最好打開,使用CvInvoke.HaveOpenCLCompatibleGpuDevice能返回是否支持.
配置CvInvoke.UseOpenCL能讓OpenCV 啟用或者停用 GPU運算

CvInvoke.UseOpenCL = CvInvoke.HaveOpenCLCompatibleGpuDevice;

構建級聯分類器對象

emgu包里已經有訓練好的數據了,文件名叫做"haarcascade_frontalface_alt.xml",就是上面添加的文件之一

var face = new CascadeClassifier("haarcascade_frontalface_alt.xml");

加載圖像並作簡單處理

在OpenCV中,大部分函數是處理灰度圖的,包括這個識別物體,所以需要轉成灰度圖,然后再調整下亮度

//加載要識別的圖片
var img = new Image<Bgr, byte>("0.png");
var img2 = new Image<Gray, byte>(img.ToBitmap());
//把圖片從彩色轉灰度
CvInvoke.CvtColor(img, img2, Emgu.CV.CvEnum.ColorConversion.Bgr2Gray);
//亮度增強
CvInvoke.EqualizeHist(img2, img2);

檢測人臉

其實這一步反而最簡單,返回的是rectangle[]格式,因為圖中可能有多個人臉,所以返回的是數組.

//在這一步就已經識別出來了,返回的是人臉所在的位置和大小
var facesDetected = face.DetectMultiScale(img2, 1.1, 10, new Size(50, 50));

剪切並保存

因為是多個人臉所以需要循環剪切並保存,(→_→)這一塊的代碼量竟然反而比上面那堆多

//循環把人臉部分切出來並保存
int count = 0;
var b = img.ToBitmap();
foreach (var item in facesDetected)
{
	count++;
	var bmpOut = new Bitmap(item.Width, item.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
	var g = Graphics.FromImage(bmpOut);
	g.DrawImage(b, new Rectangle(0, 0, item.Width, item.Height), new Rectangle(item.X, item.Y, item.Width, item.Height), GraphicsUnit.Pixel);
	g.Dispose();
	bmpOut.Save($"{count}.png", System.Drawing.Imaging.ImageFormat.Png);
	bmpOut.Dispose();
}

釋放資源退出

//釋放資源退出
b.Dispose();
img.Dispose();
img2.Dispose();
face.Dispose();

全代碼和測試圖片:

static void Main(string[] args)
{
	//如果支持用顯卡,則用顯卡運算
	CvInvoke.UseOpenCL = CvInvoke.HaveOpenCLCompatibleGpuDevice;

	//構建級聯分類器,利用已經訓練好的數據,識別人臉
	var face = new CascadeClassifier("haarcascade_frontalface_alt.xml");

	//加載要識別的圖片
	var img = new Image<Bgr, byte>("0.png");
	var img2 = new Image<Gray, byte>(img.ToBitmap());

	//把圖片從彩色轉灰度
	CvInvoke.CvtColor(img, img2, Emgu.CV.CvEnum.ColorConversion.Bgr2Gray);

	//亮度增強
	CvInvoke.EqualizeHist(img2, img2);

	//在這一步就已經識別出來了,返回的是人臉所在的位置和大小
	var facesDetected = face.DetectMultiScale(img2, 1.1, 10, new Size(50, 50));

	//循環把人臉部分切出來並保存
	int count = 0;
	var b = img.ToBitmap();
	foreach (var item in facesDetected)
	{
		count++;
		var bmpOut = new Bitmap(item.Width, item.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
		var g = Graphics.FromImage(bmpOut);
		g.DrawImage(b, new Rectangle(0, 0, item.Width, item.Height), new Rectangle(item.X, item.Y, item.Width, item.Height), GraphicsUnit.Pixel);
		g.Dispose();
		bmpOut.Save($"{count}.png", System.Drawing.Imaging.ImageFormat.Png);
		bmpOut.Dispose();
	}

	//釋放資源退出
	b.Dispose();
	img.Dispose();
	img2.Dispose();
	face.Dispose();

	return;

}

運行效果

編譯后運行可以看到目錄多了兩個圖片文件:

打開看看:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM