Sunday, June 24, 2018

Face detection_抓小偷

介紹


如果java client 端如果有偵測到人臉的話會儲存一張圖片到c:\\peoples.png
然後偵測到的人臉大於1的話則會將嫌疑人的照片儲存下來並發送一張圖片到
指定ip並告知可能有人在你家
Server 端如果有將會一直開著持續監聽

環境設定


Eclipse
Android studio
Opencv 2.49 or 48


Javacv 1.2建置


下載好javacv後建立一個eclipse 專案 jse就可以了這邊要來做監控的client,記得把這些函示庫引入

Opencv 建置


64位元就選x64,32位元就選x86

Face detection.code



package com.example.jack.myapplication;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
ServerTcpListener Server=null;
TextView IPVIEW,conter_tx;
ScrollView sco1;
ImageView img1;
int conter;
Thread t;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//顯示你的ip這我拿來看手機連到wifi的ip才能指定socket 互傳檔案
IPVIEW=(TextView) findViewById(R.id.textView);
IPVIEW.setText( getMyIp() .toString());
//用在偵測到人要變換視窗顏色
conter_tx=(TextView)findViewById(R.id.textView2) ;
sco1=(ScrollView)findViewById(R.id.sco1) ;
//開啟一個thread去呼叫server並開啟
t = new Thread(new ServerTcpListener(this));
t.start();
img1=(ImageView)findViewById(R.id.imageView);
IPVIEW.setText( "server is start!!");
}
private String getMyIp(){
//新增一個WifiManager物件並取得WIFI_SERVICE
WifiManager wifi_service = (WifiManager)getSystemService(WIFI_SERVICE);
//取得wifi資訊
WifiInfo wifiInfo = wifi_service.getConnectionInfo();
//取得IP,但這會是一個詭異的數字,還要再自己換算才行
int ipAddress = wifiInfo.getIpAddress();
//利用位移運算和AND運算計算IP
String ip = String.format("%d.%d.%d.%d",(ipAddress & 0xff),(ipAddress >> 8 & 0xff),(ipAddress >> 16 & 0xff),(ipAddress >> 24 & 0xff));
return ip;
}
}
Android server : ServerTcpListener
package com.example.jack.myapplication;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* Created by JACK on 2016/12/8.
*/
public class ServerTcpListener implements Runnable {
public MainActivity tmp;
private static Context mContext;
public static void main(String[] args) {
}
public ServerTcpListener(MainActivity tmp)
{this.tmp=tmp;
mContext=tmp;
}
public void run() {
try {
final ServerSocket server = new ServerSocket(ClientTcpSend.port);
while (true) {
try {
System.out.println("監聽中...");
Socket socket = server.accept();
System.out.println("有資料傳送!");
receiveFile(socket);
} catch (Exception e) {
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void receiveFile(Socket socket) {
byte[] inputByte = null;
int length = 0;
DataInputStream dis = null;
FileOutputStream fos = null;
try {
try {
dis = new DataInputStream(socket.getInputStream());
fos = new FileOutputStream(new
////這邊要注意如果要取得內部sd卡位置
File( Environment.getExternalStorageDirectory().getAbsolutePath()+"//aa.png"));
inputByte = new byte[1024*4];
System.out.println("開始接收檔案...");
while ((length = dis.read(inputByte, 0, inputByte.length)) > 0) {
fos.write(inputByte, 0, length);
fos.flush();
}
System.out.println("完成接收");
Bitmap bMap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"//aa.png");
///畫面即時更新ui
new Thread(new Runnable() {
public void run() {
//這邊是背景thread在運作, 這邊可以處理比較長時間或大量的運算
((Activity) mContext).runOnUiThread(new Runnable() {
public void run() {
//這邊是呼叫main thread handler幫我們處理UI部分
Bitmap bMap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"//aa.png");
tmp.img1.setImageBitmap( bMap);
tmp.conter_tx.setText("可能被侵入次數:"+tmp.conter);
tmp.conter+=1;
}
});
}
}).start();
} finally {
if (fos != null)
fos.close();
if (dis != null)
dis.close();
if (socket != null)
socket.close();
}
} catch (Exception e) {
}
}
}
package test;
import javax.swing.*;
import java.awt.Toolkit;
import java.io.File;
import java.net.URL;
import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.javacv.OpenCVFrameGrabber;
import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_imgproc.*;
import static org.bytedeco.javacpp.opencv_highgui.*;
import static org.bytedeco.javacpp.opencv_imgcodecs.*;
import static org.bytedeco.javacpp.helper.opencv_objdetect.cvHaarDetectObjects;
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 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_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;
public class test {
static OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
public static void main(String args[]) {
System.out.println("ok");
//用 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 = converter.convert(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 = converter.convert(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);
//取得捉到的人臉
//檢測到底有沒有一個人臉以上有的話則發送到server端
int total = faces.total();
if(total>0)
{
cvSaveImage("/peoples.png",img);
new ClientTcpSend();
}
//在人臉上畫一個綠色的矩型
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.GREEN, 1, CV_AA, 0);
}
//顯示圖片
cvShowImage( "Detection...", img );
cvWaitKey(200);
Toolkit toolkit = Toolkit.getDefaultToolkit();
toolkit.beep();
}
}
catch(Exception e)
{
}
}
}
//這邊的話可以看到 可以選擇要不要定時發出蜂鳴器 引起嫌犯人看鏡頭
Toolkit toolkit = Toolkit.getDefaultToolkit();
toolkit.beep();