人臉偵測其實很常見,一般的相機,手機的相機APP 都支援人臉偵測,在拍照時可以以偵測
到的人臉做為對焦區域,Face Detect基本上就是找出人臉所在的位置,本篇所使用的原理
請參考這一篇 , 在opencv中有己經訓練好的檔案可以使用,常見包含人臉偵測,雙眼偵
測,以本篇來說只要換一下訓練的檔案,程式不用改一個字,就可以改成偵測雙眼的功能。
人臉偵測和人臉識別是2個不同的東西,就好比我看到人(偵測)以及我認識這個人(識
別),是二個不同層面的事情,當然你要識出這個人之前你要先看到這個人的人臉。
程式流程如下:
取得WebCam畫面 -> 轉成灰階 ->偵測人臉位置 ->把人臉標記在WebCam畫面上 ->顯
示 -> 重頭來過
package javacv2;
import java.io.File;
import java.net.URL;
import org.bytedeco.javacpp.Loader;
import static org.bytedeco.javacpp.helper.opencv_objdetect.cvHaarDetectObjects;
import static org.bytedeco.javacpp.opencv_core.CV_AA;
import org.bytedeco.javacpp.opencv_core.CvMemStorage;
import org.bytedeco.javacpp.opencv_core.CvRect;
import org.bytedeco.javacpp.opencv_core.CvScalar;
import org.bytedeco.javacpp.opencv_core.CvSeq;
import static org.bytedeco.javacpp.opencv_core.IPL_DEPTH_8U;
import org.bytedeco.javacpp.opencv_core.IplImage;
import static org.bytedeco.javacpp.opencv_core.cvClearMemStorage;
import static org.bytedeco.javacpp.opencv_core.cvGetSeqElem;
import static org.bytedeco.javacpp.opencv_core.cvLoad;
import static org.bytedeco.javacpp.opencv_core.cvPoint;
import static org.bytedeco.javacpp.opencv_core.cvRectangle;
import static org.bytedeco.javacpp.opencv_imgproc.CV_BGR2GRAY;
import static org.bytedeco.javacpp.opencv_imgproc.cvCvtColor;
import org.bytedeco.javacpp.opencv_objdetect;
import static org.bytedeco.javacpp.opencv_objdetect.CV_HAAR_DO_CANNY_PRUNING;
import org.bytedeco.javacpp.opencv_objdetect.CvHaarClassifierCascade;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.OpenCVFrameGrabber;
public class JavaCV2 {
public static void main(String args[]) {
//用 FrameGrabber 取得 得webcam
FrameGrabber grabber = new OpenCVFrameGrabber("");
//宣告一個CanvasFrame ,就把它當作是一個JFrame用。
CanvasFrame canvas = new CanvasFrame("Webcam", CanvasFrame.getDefaultGamma() / grabber.getGamma());
//設定這一個JFrame關閉時順便把程式結束。
canvas.setDefaultCloseOperation(
javax.swing.JFrame.EXIT_ON_CLOSE);
try {
//從網路上取得訓練好的檔案(不太建議用2.4版本的會有問題)
URL url = new URL("https://raw.github.com/Itseez/opencv/2.2/data/haarcascades/haarcascade_frontalface_alt.xml");
//把網頁上取回來的資料寫入本地端檔案
File file = Loader.extractResource(url, null, "classifier", ".xml");
//假如有相同檔名己存在則刪除舊友的
file.deleteOnExit();
//指定classifier檔案名稱(也就是剛才由網路上捉下來的檔案路徑)
String classifierName = file.getAbsolutePath();
// 預先載入 opencv_objdetect module .
Loader.load(opencv_objdetect.class);
//初始化HaarClassifierCascade
CvHaarClassifierCascade classifier = new CvHaarClassifierCascade(cvLoad(classifierName));
//假如載入HaarClassifierCascade 失敗則結束程式
if (classifier.isNull()) {
System.err.println("Error loading classifier file \"" + classifierName + "\".");
System.exit(1);
}
//啟動WebCam
grabber.start();
//定義一個IplImage 存放取出來的影像
IplImage img;
//先取一張畫面放入IplImage
img = grabber.grab();
//取得影像的長寬
int width = img.width();
int height = img.height();
//建立一個灰階影像(用IPL_DEPTH_8U 原因為,灰階影像每一個pixel R,G,B值皆相等,只需要存一份即可)
IplImage grayImage = IplImage.create(width, height, IPL_DEPTH_8U, 1);
//建立一個CvMemStorage做運算用
CvMemStorage storage = CvMemStorage.create();
//設定顯示用的CanvasFrame為取出的影像大小
canvas.setCanvasSize(grabber.getImageWidth(),
grabber.getImageHeight());
while (canvas.isVisible() && (img = grabber.grab()) != null) {
//重置運算用的CvMemStorage
cvClearMemStorage(storage);
// 把原始影像變成灰階
cvCvtColor(img, grayImage, CV_BGR2GRAY);
//偵測人臉
CvSeq faces = cvHaarDetectObjects(grayImage, classifier, storage,
1.1, 3, CV_HAAR_DO_CANNY_PRUNING);
//取得捉到的人臉
int total = faces.total();
//在人臉上畫一個紅色的矩型
for (int i = 0; i < total; i++) {
CvRect r = new CvRect(cvGetSeqElem(faces, i));
int x = r.x(), y = r.y(), w = r.width(), h = r.height();
cvRectangle(img, cvPoint(x, y), cvPoint(x + w, y + h), CvScalar.RED, 1, CV_AA, 0);
}
//顯示圖片
canvas.showImage(img);
}
}
catch(Exception e)
{
}
}
}
至於主要用來偵測的cvHaarDetectObjects 用法如下 -資料來源
cvHaarDetectObjects( const CvArr* image, CvHaarClassifierCascade* cascade,
CvMemStorage* storage, double scale_factor=1.1,
int min_neighbors=3, int flags=0,
CvSize min_size=cvSize(0,0) );
- image
- 被檢圖像
- cascade
- harr 分類器級聯的內部標識形式
- storage
- 用來存儲檢測到的一序列候選目標矩形框的記憶體區域。
- scale_factor
- 在前後兩次相繼的掃描中,搜索視窗的比例繫數。例如1.1指將搜索視窗依次擴大10%。
- min_neighbors
- 構成檢測目標的相鄰矩形的最小個數(預設-1)。如果組成檢測目標的小矩形的個數和小於min_neighbors-1 都會被排除。如果min_neighbors 為 0, 則函數不做任何操作就返回所有的被檢候選矩形框,這種設定值一般用在用戶自定義對檢測結果的組合程式上。
- flags
- 操作方式。當前唯一可以定義的操作方式是 CV_HAAR_DO_CANNY_PRUNING。如果被設定,函數利用Canny邊緣檢測器來排除一些邊緣很少或者很多的圖像區域,因為這樣的區域一般不含被檢目標。人臉檢測中通過設定閾值使用了這種方法,並因此提高了檢測速度。
- min_size
- 檢測視窗的最小尺寸。預設的情況下被設為分類器訓練時採用的樣本尺寸(人臉檢測中預設大小是~20×20)。
接下來我們把程式中的
//從網路上取得訓練好的檔案(不太建議用2.4版本的會有問題)
URL url = new URL("https://raw.github.com/Itseez/opencv/2.2/data/haarcascades/haarcascade_frontalface_alt.xml");
換成
//從網路上取得訓練好的檔案(不太建議用2.4版本的會有問題)
URL url = new URL("https://raw.githubusercontent.com/Itseez/opencv/2.2/data/haarcascades/haarcascade_eye_tree_eyeglasses.xml");
網路上也有一些訓練好的檔案的資料可以使用,不限於只有人臉或雙眼,參考下列網址 https://github.com/Itseez/opencv/tree/master/data/haarcascades
沒有留言:
張貼留言