基於開源專案OpenCV的人臉識別Demo版整理(不僅可以識別人臉,還可以識別眼睛鼻子嘴等)【模式識別中的翹楚】
最近對人臉識別的程式非常感興趣,但是苦於沒有選修多媒體方向,看了幾篇關於人臉識別的論文,大概也沒看懂多少,什麼灰度處理啊,切割識別啊,雲裡霧裡,傻傻看不明白啊。各種苦惱。
於是就在網上找找,看有木有神馬開原始碼啊,要是有個現成的原始碼就更好了,百度it ,那些原始碼都憂傷的躲在CSDN中,老衲還是光頭沒積分型別的,沒有辦法,偶爾找幾個不用積分的連結吧,妹的,download的好幾天,都沒下來1K,徹底被打敗了。
一狠心一咬牙,自己幹了。毛爺爺教育我們說,自己動手,不愁吃喝拉撒睡。於是開始找開源的程式碼,開始我還天真的尋找Java版的,後來才明白,java的 運算能力根本不被大家認可,像人臉識別這種需要很高運算能力的,需要很高效率的事情,都只有C/C++的。後來就看到了OpenCV這個開源專案,一點一 點開始,終於完成了Demo版本,先晒幾張識別的照片,然後再談談Demo實現過程。
(本來想用本人靚照,後來想想,怕大家嚇怕了不敢繼續讀下去,還是找明星吧
這是載入影象後再通過影象識別,找到人臉,畫出人臉區域的紅圈後的效果。
一、OpenCV介紹
OpenCV的全稱是Open Source Computer Vision Library,是一個跨平臺的計算機視覺庫。OpenCV是由英特爾公司發起並參與開發,以BSD許可證授權發行,可以在商業和研究領域中免費使用。OpenCV可用於開發實時的影象處理、計算機視覺以及模式識別程式。
計算機視覺的應用領域越來越廣泛,無論從手機應用,行為分析,文書處理還有遊戲設計等,在很多地方已經投入了應用生產,而不學一點視覺的東西感覺自己都會落後了,哈哈。目前很多的計算機視覺的軟體都有其侷限性,成本高,開發週期長,沒有固定統一的API設計等等。
OpenCV在Intel公司發起後,不僅在這些問題上給了很多獨特的解決方案,同時還可以安裝Intel公司的IPP來進行加速處理。作為我們學習,就不必購買IPP,直接使用開源的OpenCV足以解決很多問題。
二、OpenCV安裝總結(在Windows環境下,如果需要了解Linux下的安裝過程,可以去官方的http://www.opencv.org.cn/forum/尋找解決辦法)
1.安裝VS2008,相信這個都沒問題。VC++2008Express也可以
2.安裝OpenCV2.0版本。
這個解釋一下啊,現在OpenCV已經出到了2.3版本,但是2.0是目前穩定的最新本,因為OpenCV是開源的專案,在持續的開發中,而2.0網上的介紹大多基於此,新版本的改進還很少詳細的介紹。所以2.0已經足夠用了。下載地址
下載後安裝,我安裝在了D:\Program Files\OpenCV2.0下
3.安裝CMake
CMake的百科解釋:CMake 是個跨平臺的自動化建構系統,它用組態檔控制建構過程(build process)的方式和 Unix 的 Make 相似,只是 CMake 的組態檔取名為 CmakeLists.txt。Cmake 並不直接建構出最終的軟體,而是產生標準的建構檔(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然後再依一般的建構方式使用。這使得熟悉某個整合開發環境(IDE)的開發者可以用標準的方式建構他的軟體,這種可以使用各平臺的原生建構系統的能力是 CMake 和 SCons 等其他類似系統的區別之處。CMake 可以編譯原始碼、製作程式庫、產生介面卡(wrapper)、還可以用任意的順序建構執行檔、
我的理解就是CMake是個開源的專案,用於構建原始碼,但是它構建不生成可用檔案,而是按照你喜歡的方式幫你構建原始碼,構建成特定IDE可用的工程。
一會需要用到它來幫助我們將OpenCV原始碼編譯成VS可用的工程。
4.用CMake匯出VC++專案檔案
- 執行cmake-gui,設定路徑為OpenCV安裝路徑(本文件假定安裝位置為:D:\Program Files\OpenCV2.0),並建立子目錄D:\Program Files\OpenCV2.0\vc2008,用於存放編譯結果。
- 然後點 configure,在彈出的對話方塊內選擇 Visual Studio 9 2008。
- 如果是VC++2008的Express版本,則不支援OpenMP,所以需要取消ENABLE_OPENMP選項,取消後再次選擇“Congfigure”,完成後選擇“Generate”。VC++ 2008(不是Express版本)支援OpenMP,如果你使用VC++2008,強烈建議不要取消這個選項。
注意:OpenCV2.1中沒有ENABLE_OPENMP選項,在安裝VC++2008時可以不管這個選項。
點選看大圖 |
點選看大圖 |
點選看大圖 |
5.編譯 OpenCV Debug和Release版本庫
完成上一步驟後,將在D:\Program Files\OpenCV2.0\vc2008目錄下生成OpenCV.sln的VC Solution File,請用VC++ 2008 Express開啟OpenCV.sln,然後執行如下操作:
- 在Debug下,選擇Solution Explorer裡的 Solution OpenCV,點右鍵,執行"Rebuild Solution";如編譯無錯誤,再選擇INSTALL專案,執行"Build"。
- 在Release下,選擇Solution Explorer裡的 Solution OpenCV,點右鍵,執行"Rebuild Solution";如編譯無錯誤,再選擇INSTALL專案,執行"Build"。
此時,OpenCV的*d.dll檔案(for debug)和*.dll檔案(for release)將出現在D:\Program Files\OpenCV2.0\vc2008\bin目錄中;OpenCV的*d.lib檔案(for debug)和*.lib檔案(for release)將出現在D:\Program Files\OpenCV2.0\vc2008\lib目錄;標頭檔案*.h出現在D:\Program Files\OpenCV2.0\vc2008\include\opencv中。
可以被VC++ 2008 Express呼叫的OpenCV動態庫生成完畢
點選看大圖 |
點選看大圖 |
點選看大圖 |
點選看大圖 |
點選看大圖 |
6.配置Windows環境變數Path
將D:\Program Files\OpenCV2.0\vc2008\bin加入Windows系統環境變數Path中。加入後可能需要登出當前Windows使用者(或重啟)後重新登陸才生效。
點選看大圖 |
點選看大圖 |
7.為VC++ 2008 Express配置OpenCV環境
開啟VC++ 2008 Express,選單 Tools -> Options -> Projects and Solutions -> VC++ Directories
- Show directories for選擇executable files,加入目錄 D:\Program Files\OpenCV2.0\vc2008\bin
- Show directories for選擇include files,加入目錄 D:\Program Files\OpenCV2.0\vc2008\include\opencv
- Show directories for選擇library files,加入目錄 D:\Program Files\OpenCV2.0\vc2008\lib
關閉VC++ 2008 Express。
點選看大圖 |
點選看大圖 |
OK,到現在為止呢,我們就配置好了環境可以使用OpenCV來程式設計,下面將介紹如何使用OpenCV,編寫人臉識別的程式碼。
二、人臉識別程式編寫。
1.首先建立一個機遇對話方塊的MFC工程FaceDetection2。
檔案如圖:
2.將對話方塊修改成如圖所示
3.按照如下步驟配置用到的lib
- 選擇Solution Explorer裡的FaceDetection2專案,點選滑鼠右鍵,選擇Properties,在[連結器 LINKER]的[輸入INPUT]中:
- 為專案的Debug配置增加 [依賴的庫 Additional Dependencies]:cxcore200d.lib cv200d.lib highgui200d.lib(注意,檔名cv200d.lib 可能是cv***d.lib等形式,具體應檢視D:\Program Files\OpenCV2.0\vc2008\lib。如果使用的是OpenCV2.1,應輸入:cxcore210d.lib cv210d.lib highgui210d.lib )
- 為專案的Release配置增加[依賴的庫 Additional Dependencies]:cxcore200.lib cv200.lib highgui200.lib (注意:如果使用的是OpenCV2.1,應輸入:cxcore210.lib cv210.lib highgui210.lib)
- 在 [配置屬性 Configuration Properties]- [General] -[字符集 Character Set] 修改為使用“多位元組字符集” (由於2008預設是以Unicode字符集編譯的
4.然後編輯FaceDetection2Dlg.cpp檔案,原始碼如下
// FaceDetection2Dlg.cpp : implementation file
//
#include "stdafx.h"
#include "FaceDetection2.h"
#include "FaceDetection2Dlg.h"
#include <string.h>
#include <iostream>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
using namespace std;
const char* cascade_name="haarcascade_frontalface_alt2.xml";//分類器的名稱
const char* cascade_name1="haarcascade_eye_tree_eyeglasses.xml";//分類器的名稱
const char* cascade_name2="haarcascade_frontalface_alt_tree.xml";//分類器的名稱
const char* cascade_name3="haarcascade_mcs_mouth.xml";//分類器的名稱
const char* cascade_name4="haarcascade_mcs_nose.xml";//分類器的名稱
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CFaceDetection2Dlg dialog
CFaceDetection2Dlg::CFaceDetection2Dlg(CWnd* pParent /*=NULL*/)
: CDialog(CFaceDetection2Dlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CFaceDetection2Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CFaceDetection2Dlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(ID_FaceDetected, &CFaceDetection2Dlg::OnBnClickedFacedetected)
END_MESSAGE_MAP()
// CFaceDetection2Dlg message handlers
BOOL CFaceDetection2Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CFaceDetection2Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CFaceDetection2Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CFaceDetection2Dlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CFaceDetection2Dlg::OnBnClickedFacedetected()
{
// TODO: 在此新增命令處理程式程式碼
CString fileName;
//開啟檔案對話視窗
CFileDialog OpenDlg( TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR, L"影象檔案格式JPG file format (*.jpg)|*.jpg|(*.bmp) |*.bmp|", NULL);
//從檔案對話視窗中開啟影象
if(OpenDlg.DoModal()!=IDOK)
return ;
//獲得檔名
fileName = OpenDlg.GetPathName();
//必要的型別轉換
std::string tempName = (LPCSTR)CStringA(fileName);
const char* tmp = tempName.c_str();
//開啟檔案,若失敗則返回
if((src=cvLoadImage(tmp,CV_LOAD_IMAGE_ANYCOLOR))==0)
return ;
//載入(分類器層疊)訓練庫
cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name2, 0, 0, 0 );
//載入不成功則顯示錯誤訊息,並退出
if(cascade)
{
storage = cvCreateMemStorage(0);
cvNamedWindow( "人臉檢測", CV_WINDOW_AUTOSIZE ); //建立視窗
//如果圖片存在則分析並顯示結果,否則退出程式
if(src)
detect_and_draw(src);//呼叫人臉檢與標示事件
cvReleaseImage(&src);
cvReleaseMemStorage( &storage );
}else{
AfxMessageBox(L"無法載入分類器,請確認後重試!");
}
cvReleaseHaarClassifierCascade( &cascade );
}
void CFaceDetection2Dlg::detect_and_draw(IplImage *img)
{
static CvScalar color[] = {{0,0,255},{0,128,255},{0,255,255},{0,255,0},{0,128,255},{255,128,0},{255,255,0},{255,0,0},{255,0,255}};//用於設定標示影象中人臉的顏色
double scale = 1.3;
IplImage* gray = cvCreateImage(cvSize(img->width,img->height),8,1);
IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),cvRound (img->height/scale)),8,1 );
int i;
cvCvtColor( img, gray, CV_BGR2GRAY );
cvResize( gray, small_img, CV_INTER_LINEAR );
cvEqualizeHist( small_img, small_img );
cvClearMemStorage( storage );
if( cascade )
{
//檢測人臉
CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage, 1.1, 2, 0, cvSize(30, 30) );
for( i = 0; i < (faces ? faces->total : 0); i++ )
{
CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
CvPoint center;
int radius;
center.x = cvRound((r->x + r->width*0.5)*scale);
center.y = cvRound((r->y + r->height*0.5)*scale);
radius = cvRound((r->width + r->height)*0.25*scale);
cvCircle( img, center, radius, color[i], 3, 8, 0 );
}
}
cvShowImage( "人臉檢測", img );
cvReleaseImage( &gray );
cvReleaseImage( &small_img );
}
其中OnBnClickedFacedetected()為按鈕FaceDetect的監聽方法
detect_and_draw(IplImage *img)方法用於檢測人臉
5.執行觀察結果
三、總結
在原始碼中,
const char* cascade_name="haarcascade_frontalface_alt2.xml";//分類器的名稱
const char* cascade_name1="haarcascade_eye_tree_eyeglasses.xml";//分類器的名稱
const char* cascade_name2="haarcascade_frontalface_alt_tree.xml";//分類器的名稱
const char* cascade_name3="haarcascade_mcs_mouth.xml";//分類器的名稱
const char* cascade_name4="haarcascade_mcs_nose.xml";//分類器的名稱
這是不同的分類器,你可以在你安裝的OpenCV中找到。如D:\Program Files\OpenCV2.0\vs2008\data\haarcascades
不同分類器能夠幫助你識別不同的部分,如眼睛,鼻子和嘴,更多的需要自己去探索吧。
求分享求推薦。啊
相關推薦
基於開源專案OpenCV的人臉識別Demo版整理(不僅可以識別人臉,還可以識別眼睛鼻子嘴等)【模式識別中的翹楚】
最近對人臉識別的程式非常感興趣,但是苦於沒有選修多媒體方向,看了幾篇關於人臉識別的論文,大概也沒看懂多少,什麼灰度處理啊,切割識別啊,雲裡霧裡,傻傻看不明白啊。各種苦惱。 於是就在網上找找,看有木有神馬開原始碼啊,要是有個現成的原始碼就更好了,百度it ,那些原始碼都憂傷的躲在CSDN中,老衲還
基於開源專案OpenCV的人臉識別Demo版整理(不僅可以識別人臉,還可以識別眼睛鼻子嘴等)
最近對人臉識別的程式非常感興趣,但是苦於沒有選修多媒體方向,看了幾篇關於人臉識別的論文,大概也沒看懂多少,什麼灰度處理啊,切割識別啊,雲裡霧裡,傻傻看不明白啊。各種苦惱。 於是就在網上找找,看有木有神馬開原始碼啊,要是有個現成的原始碼就更好了,百度it ,那些
基於Taro + Dva構建的適配不同端(微信小程式、H5、React-Native 等)的時裝衣櫥
前言 Taro 是一套遵循 React 語法規範的 多端開發 解決方案。現如今市面上端的形態多種多樣,Web、React-Native、微信小程式等各種端大行其道,當業務要求同時在不同的端都要求有所表現的時候,針對不同的端去編寫多套程式碼的成本顯然非常高,這時候只編寫一套程式碼就能夠適配到多端的能力就顯得極
Android基於開源專案的WheelView的時間、地址聯動選擇對話方塊
一晃離上次寫部落格差不多都過了半年了,現在工作中用到了一些實用的東西,想和大家分享一下。現在實現的是一個基於開源專案WheelView的時間、地址聯動選擇的對話方塊,先看看效果圖,文章末尾有原始碼下載地址:選擇時間:選擇地點:因為專案中要實現如圖上的效果,無奈
.NET ORM 開源專案 FreeSql 1.0 正式版釋出
一、簡介 FreeSql 是 .NET 平臺下的物件關係對映技術(O/RM),支援 .NetCore 2.1+ 或 .NetFramework 4.0+ 或 Xamarin。 從 0.0.1 釋出,歷時整整一年的迭代更新,原計劃元旦釋出1.0,可能作者比較急提前了幾天釋出。其實是元旦有其他事…… 本文內容從簡
【模式識別與機器學習】——判別式和產生式模型
(1)判別式模型(Discriminative Model)是直接對條件概率p(y|x;θ)建模。常見的判別式模型有線性迴歸模型、線性判別分析、支援向量機SVM、神經網路、boosting、條件隨機場等。 舉例:要確定一個羊是山羊還是綿羊,用判別模型的方法是從歷史資料中學習到模型,然後通過提取這隻羊的特
【模式識別與機器學習】——3.9勢函式法:一種確定性的非線性分類方法
目的 用勢函式的概念來確定判別函式和劃分類別介面。 基本思想 假設要劃分屬於兩種類別ω1和ω2的模式樣本,這些樣本可看成是分佈在n維模式空間中的點xk。 把屬於ω1的點比擬為某種能源點,在點上,電位達到峰值。 隨著與該點距離的增大,電位分佈迅速減小,即把樣本xk附近空間x點上的電位分佈,看
TensorFlow 學習(六)時尚(衣服、鞋、包等) Fashion MNIST識別
使用 jupyter notebook 筆記,匯入需要的包 # TensorFlow and tf.keras import tensorflow as tf from tensorflow import keras import numpy as np import numpy as np
【模式識別與機器學習】——PCA主成分分析
基本思想 其基本思想就是設法提取資料的主成分(或者說是主要資訊),然後摒棄冗餘資訊(或次要資訊),從而達到壓縮的目的。本文將從更深的層次上討論PCA的原理,以及Kernel化的PCA。 引子 首先我們來考察一下,這裡的資訊冗餘是如何體現的。如下圖所示,我們有一組二維資料點,從圖上不難發現
【模式識別與機器學習】——PCA與Kernel PCA介紹與對比
PCA與Kernel PCA介紹與對比 1. 理論介紹 PCA:是常用的提取資料的手段,其功能為提取主成分(主要資訊),摒棄冗餘資訊(次要資訊),從而得到壓縮後的資料,實現維度的下降。其設想通過投影矩陣將高維資訊轉換到另一個座標系下,並通過平移將資料均值變為零。PCA認為,在變換過後的
【模式識別與機器學習】——最大似然估計 (MLE) 最大後驗概率(MAP)
1) 極/最大似然估計 MLE 給定一堆資料,假如我們知道它是從某一種分佈中隨機取出來的,可是我們並不知道這個分佈具體的參,即“模型已定,引數未知”。例如,我們知道這個分佈是正態分佈,但是不知道均值和方差;或者是二項分佈,但是不知道均值。 最大似然估計(MLE,Maximum Likelihood Esti
學習筆記之——基於pytorch的SFTGAN(xintao程式碼學習,及資料處理部分的學習)
程式碼的框架仍然是——《https://github.com/xinntao/BasicSR》 給出SFTGAN的論文《Recovering Realistic Texture in Image Super-resolution by Deep Spatial Feature Transfo
記錄使用Vue相關API開發專案時遇到的問題難點整理(不定時更新)
本文為整理記錄本人從17年初開始上手使用Vue以後,針對專案中業務需求所遇到到的各種問題及難點的解決方法整理?。 1、keep-alive元件快取: <!--這裡是需要快取的--> <keep-alive> <router-v
python3繪圖示例6-2(基於matplotlib,繪圖流程介紹及設定等)
#!/usr/bin/env python# -*- coding:utf-8 -*-import osimport numpy as npimport matplotlib as mpltfrom matplotlib import pyplot as pltfrom matplotlib.ticker i
python3繪圖示例6-1(基於matplotlib,繪圖流程介紹及設定等)
#!/usr/bin/env python# -*- coding:utf-8 -*-import osimport pylab as pyimport numpy as npfrom matplotlib import pyplot as pltimport matplotlib as mplt# matp
嵌入式學習中較好的練手專案和課題整理(附程式碼資料、學習視訊和嵌入式學習規劃)
0、引言 何為嵌入式? IEEE官方定義:Devices Used to Control,Monitor Assist the Operation of Equipment,Machinery or Plants。 翻譯過來就是:用於“控制、監視或者
SparkStreaming部分:OutPutOperator類,SaveAsHadoopFile運算元(實際上底層呼叫textFileStream讀取的,跟前兩種有一些區別)【Java版純程式碼】
package streamingOperate.output; import java.util.Arrays; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; imp
Java實現百度雲OCR介面識別圖片文字資訊(也包含身份證,銀行卡識別,更新新增通用票據識別)
1.需求背景 因專案需求,需要提取身份證、發票(9/16更新內容)、榮譽證書上的文字資訊,與相關檔案進行匹配,而查閱相關資料,經過對比之後,發現用百度OCR文字識別API服務可以相應解決相關問題,識別率較好。當然,還不能夠做到完全匹配,也有其中不足的地方,例如,發票中公章資訊不能提取;發票周
【模式識別】SVM核函式
以下是幾種常用的核函式表示:線性核(Linear Kernel)多項式核(Polynomial Kernel)徑向基核函式(Radial Basis Function)也叫高斯核(Gaussian Kernel),因為可以看成如下核函式的領一個種形式:徑向基函式是指取值僅僅依
【模式識別】Fisher線性判別
Fisher是一種將高維空間對映到低維空間降維後進行分類的方法 1.投影: 對xn→的分量作線性組合可得標量 yn=w⃗ Txn→ 什麼樣的對映方法是好的,我們需要設計一個定量的標準去找w⃗ 來