[機器學習筆記]kNN進鄰算法

K-近鄰算法

一、算法概述

(1)採用測量不同特徵值之間的距離方法進行分類

  • 優點: 精度高、對異常值不敏感、無數據輸入假定。
  • 缺點: 計算複雜度高、空間複雜度高。

(2)KNN模型的三個要素

kNN算法模型實際上就是對特徵空間的的劃分。模型有三個基本要素:距離度量、K值的選擇和分類決策規則的決定。

  • 距離度量

    距離定義為:
    \[L_p(x_i,x_j)=\left( \sum^n_{l=1} |x_i^{(l)} – x_j^{(l)}|^p \right) ^{\frac{1}{p}}\]
    一般使用歐式距離:p = 2的個情況
    \[L_p(x_i,x_j)=\left( \sum^n_{l=1} |x_i^{(l)} – x_j^{(l)}|^2 \right) ^{\frac{1}{2}}\]

  • K值的選擇

    一般根據經驗選擇,需要多次選擇對比才可以選擇一個比較合適的K值。

    如果K值太小,會導致模型太複雜,容易產生過擬合現象,並且對噪聲點非常敏感。

    如果K值太大,模型太過簡單,忽略的大部分有用信息,也是不可取的。

  • 分類決策規則

    一般採用多數表決規則,通俗點說就是在這K個類別中,哪種類別最後就判別為哪種類型

二、實施kNN算法

2.1 偽代碼

  • 計算法已經類別數據集中的點與當前點之間的距離
  • 按照距離遞增次序排序
  • 選取與但前點距離最小的k個點
  • 確定前k個點所在類別的出現頻率
  • 返回前k個點出現頻率最高的類別作為當前點的預測分類

2.2 實際代碼

def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]
    diffMat = tile(inX, (dataSetSize,1)) - dataSet
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances**0.5
    sortedDistIndicies = distances.argsort()     
    classCount={}          
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

三、實際案例:使用kNN算法改進約會網站的配對效果

我的朋友阿J一直使用在線約會軟件尋找約會對象,他曾經交往過三種類型的人:

  • 不喜歡的人
  • 感覺一般的人
  • 非常喜歡的人

步驟:

  • 收集數據
  • 準備數據:也就是讀取數據的過程
  • 分析數據:使用Matplotlib畫出二維散點圖
  • 訓練算法
  • 測試算法
  • 使用算法

3.1 準備數據

樣本數據共有1000個,3個特徵值,共有4列數據,最後一列表示標籤分類(0:不喜歡的人;1:感覺一般的人;2:非常喜歡的人)

特徵

  • 每年獲得的飛行常客里程數
  • 玩視頻遊戲所好的時間百分比
  • 每周消費的冰淇淋公斤數

部分數據如下:

40920   8.326976    0.953952    3
14488   7.153469    1.673904    2
26052   1.441871    0.805124    1
75136   13.147394   0.428964    1
38344   1.669788    0.134296    1
72993   10.141740   1.032955    1
35948   6.830792    1.213192    3
42666   13.276369   0.543880    3
67497   8.631577    0.749278    1
35483   12.273169   1.508053    3

讀取數據(讀取txt文件)

def file2matrix(filename):
    fr = open(filename)
    numberOfLines = len(fr.readlines())         #get the number of lines in the file
    returnMat = zeros((numberOfLines,3))        #prepare matrix to return
    classLabelVector = []                       #prepare labels return   
    fr = open(filename)
    index = 0
    for line in fr.readlines():
        line = line.strip()
        listFromLine = line.split('\t')
        returnMat[index,:] = listFromLine[0:3]
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat,classLabelVector

3.2 分析數據:使用Matplotlib創建散點圖

初步分析
import matplotlib
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1], datingDataMat[:,2])
ax.set_xlabel("玩視頻遊戲所耗時間百分比")
ax.set_ylabel("每周消費的冰淇淋公斤數")
plt.show()

因為有三種類型的分類,這樣看的不直觀,我們添加以下顏色

fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1], datingDataMat[:,2])
ax.scatter(datingDataMat[:,1], datingDataMat[:,2], 15.0*array(datingLabels), 15.0*array(datingLabels))
ax.set_xlabel("玩視頻遊戲所耗時間百分比")
ax.set_ylabel("每周消費的冰淇淋公斤數")
plt.show()

通過都多次的嘗試后發現,玩遊戲時間和冰淇淋這個兩個特徵關係比較明顯

具體的步驟:

  • 分別將標籤為1,2,3的三種類型的數據分開
  • 使用matplotlib繪製,並使用不同的顏色加以區分
datingDataType1 = array([[x[0][0],x[0][1],x[0][2]] for x in zip(datingDataMat,datingLabels) if x[1]==1])
datingDataType2 = array([[x[0][0],x[0][1],x[0][2]] for x in zip(datingDataMat,datingLabels) if x[1]==2])
datingDataType3 = array([[x[0][0],x[0][1],x[0][2]] for x in zip(datingDataMat,datingLabels) if x[1]==3])
                   

fig, axs = plt.subplots(2, 2, figsize = (15,10))
axs[0,0].scatter(datingDataType1[:,0], datingDataType1[:,1], s = 20, c = 'red')
axs[0,1].scatter(datingDataType2[:,0], datingDataType2[:,1], s = 30, c = 'green')
axs[1,0].scatter(datingDataType3[:,0], datingDataType3[:,1], s = 40, c = 'blue')
type1 = axs[1,1].scatter(datingDataType1[:,0], datingDataType1[:,1], s = 20, c = 'red')
type2 = axs[1,1].scatter(datingDataType2[:,0], datingDataType2[:,1], s = 30, c = 'green')
type3 = axs[1,1].scatter(datingDataType3[:,0], datingDataType3[:,1], s = 40, c = 'blue')
axs[1,1].legend([type1, type2, type3], ["Did Not Like", "Liked in Small Doses", "Liked in Large Doses"], loc=2)
axs[1,1].set_xlabel("玩視頻遊戲所耗時間百分比")
axs[1,1].set_ylabel("每周消費的冰淇淋公斤數")

plt.show()

3.3 準備數據:數據歸一化

通過上面的圖形繪製,發現三個特徵值的範圍不一樣,在使用KNN進行計算距離的時候,數值大的特徵值就會對結果產生更大的影響。

數據歸一化:就是將幾組不同範圍的數據,轉換到同一個範圍內。

公式: newValue = (oldValue – min)/(max – min)

def autoNorm(dataSet):
    minVals = dataSet.min(0) # array([[1,20,3], [4,5,60], [7,8,9]])   min(0) = [1, 5, 3]
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normData = zeros(shape(dataSet))
    m = dataSet.shape[0]
    normData = (dataSet - tile(minVals, (m,1)))/tile(ranges,(m,1))
    return normData

3.4 測試算法

我們將原始樣本保留20%作為測試集,剩餘80%作為訓練集

def datingClassTest():
    hoRatio = 0.20  
    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')       #load data setfrom file
    normMat = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m*hoRatio)
    errorCount = 0.0
    for i in range(numTestVecs):
        classifierResult = classify0(normMat[i,:],normMat[numTestVecs:,:],datingLabels[numTestVecs:],3)
        if (classifierResult != datingLabels[i]): 
            errorCount += 1.0
    print ("the total error rate is: %f" % (errorCount/float(numTestVecs)))
    print (errorCount)

運行結果

the total error rate is: 0.080000
16.0

四、源代碼

from numpy import *
import operator
from os import listdir

import matplotlib
import matplotlib.pyplot as plt
    
## KNN function
def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]
    diffMat = tile(inX, (dataSetSize,1)) - dataSet
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances**0.5
    sortedDistIndicies = distances.argsort()     
    classCount={}          
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

# read txt data
def file2matrix(filename):
    fr = open(filename)
    numberOfLines = len(fr.readlines())         #get the number of lines in the file
    returnMat = zeros((numberOfLines,3))        #prepare matrix to return
    classLabelVector = []                       #prepare labels return   
    fr = open(filename)
    index = 0
    for line in fr.readlines():
        line = line.strip()
        listFromLine = line.split('\t')
        returnMat[index,:] = listFromLine[0:3]
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat,classLabelVector


def autoNorm(dataSet):
    minVals = dataSet.min(0) # array([[1,20,3], [4,5,60], [7,8,9]])   min(0) = [1, 5, 3]
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normData = zeros(shape(dataSet))
    m = dataSet.shape[0]
    normData = (dataSet - tile(minVals, (m,1)))/tile(ranges,(m,1))
    return normData
    
    
    
    
def drawScatter1(datingDataMat, datingLabels):
    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(datingDataMat[:,1], datingDataMat[:,2])
    ax.set_xlabel("玩視頻遊戲所耗時間百分比")
    ax.set_ylabel("每周消費的冰淇淋公斤數")
    plt.show()
    
def drawScatter2(datingDataMat, datingLabels):
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(datingDataMat[:,1], datingDataMat[:,2])
    ax.scatter(datingDataMat[:,1], datingDataMat[:,2], 15.0*array(datingLabels), 15.0*array(datingLabels))
    ax.set_xlabel("玩視頻遊戲所耗時間百分比")
    ax.set_ylabel("每周消費的冰淇淋公斤數")
    plt.show()
    
    
def drawScatter3(datingDataMat, datingLabels):
    datingDataType1 = array([[x[0][0],x[0][1],x[0][2]] for x in zip(datingDataMat,datingLabels) if x[1]==1])
    datingDataType2 = array([[x[0][0],x[0][1],x[0][2]] for x in zip(datingDataMat,datingLabels) if x[1]==2])
    datingDataType3 = array([[x[0][0],x[0][1],x[0][2]] for x in zip(datingDataMat,datingLabels) if x[1]==3])

    fig, axs = plt.subplots(2, 2, figsize = (15,10))
    axs[0,0].scatter(datingDataType1[:,0], datingDataType1[:,1], s = 20, c = 'red')
    axs[0,1].scatter(datingDataType2[:,0], datingDataType2[:,1], s = 30, c = 'green')
    axs[1,0].scatter(datingDataType3[:,0], datingDataType3[:,1], s = 40, c = 'blue')
    type1 = axs[1,1].scatter(datingDataType1[:,0], datingDataType1[:,1], s = 20, c = 'red')
    type2 = axs[1,1].scatter(datingDataType2[:,0], datingDataType2[:,1], s = 30, c = 'green')
    type3 = axs[1,1].scatter(datingDataType3[:,0], datingDataType3[:,1], s = 40, c = 'blue')
    axs[1,1].legend([type1, type2, type3], ["Did Not Like", "Liked in Small Doses", "Liked in Large Doses"], loc=2)
    axs[1,1].set_xlabel("玩視頻遊戲所耗時間百分比")
    axs[1,1].set_ylabel("每周消費的冰淇淋公斤數")

    plt.show()
    
    
    
def datingClassTest():
    hoRatio = 0.20  
    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')       #load data setfrom file
    normMat = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m*hoRatio)
    errorCount = 0.0
    for i in range(numTestVecs):
        classifierResult = classify0(normMat[i,:],normMat[numTestVecs:,:],datingLabels[numTestVecs:],3)
        if (classifierResult != datingLabels[i]): 
            errorCount += 1.0
    print ("the total error rate is: %f" % (errorCount/float(numTestVecs)))
    print (errorCount)
    
    
datingDataMat, datingLabels = file2matrix("datingTestSet2.txt")

drawScatter1(datingDataMat, datingLabels)
drawScatter2(datingDataMat, datingLabels)
drawScatter3(datingDataMat, datingLabels)
 
datingClassTest()

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

windows搭建MongoDB副本集及開啟身份驗證

MongoDB副本集搭建

我搭建的是一個主節點,兩個副節點

  1. 構建目錄結構如下圖所示

  2. rs0是副本集名稱,每一份文件都是一個端口服務,以27018為主節點。

 

每一份的目錄結構如下,conf存放的是配置文件信息,data27018是存放數據庫數據信息,keyfile是存放key文件的。用於各個節點之間的身份驗證。log存放數據庫的日誌信息,用來排查問題。

 

  3.conf文件

Conf是放配置文件

# mongod.conf

# for documentation of all options, see:

#   http://docs.mongodb.org/manual/reference/configuration-options/

# Where and how to store data.

storage:

  dbPath: D:\MongoDB\rs0\27018\data27018

  journal:

    enabled: true

#  engine:

#  mmapv1:

#  wiredTiger:

# where to write logging data.

systemLog:

  destination: file

  logAppend: true

  path:  D:\MongoDB\rs0\27018\log27018\mongo.log

# network interfaces

net:

  port: 27018

  bindIp: 0.0.0.0

#processManagement:

security:

  authorization: enabled

  keyFile: D:\MongoDB\rs0\27018\keyfile\replicaSet1.key

#operationProfiling:

replication:

  oplogSizeMB: 2048

  replSetName: rs0

#sharding:

  #clusterRole: shardsvr

## Enterprise-Only Options:

#auditLog:

#snmp:

4.Keyfile下有個.key的文件為了複製集的用戶驗證。(keyfile文件是需要base編碼且差不多660個字符。權限)

可用Linux系統生成,或者找度娘。每一個端口服務下的key必須是同一個。

5.修改每一個實例的conf文件里的端口號及數據存放地址,日誌等。

6.運行win+r 選擇管理員啟動cmd

Windows註冊服務

Windows註冊服務
mongod.exe --config "D:\MongoDB\rs0\27018\conf\mongo.conf" --serviceName "MongoDB27018" --serviceDisplayName "MongoDB27018" –install

mongod.exe --config "D:\MongoDB\rs0\27019\conf\mongo.conf" --serviceName "MongoDB27019" --serviceDisplayName "MongoDB27019" –install

mongod.exe --config "D:\MongoDB\rs0\27020\conf\mongo.conf" --serviceName "MongoDB27020" --serviceDisplayName "MongoDB27020" --install

安裝成服務后可以到服務中查看。

 7.註冊完成后,將所有服務啟動

8.重新打開cmd  連接到其中的一個mongodb實例命令為:   mongo –host ip地址 –port 27018

9.再連接其他兩個實例

10.進入27018節點進行初始化配置

輸入命令

其中的localhost 應是本機的IP地址。(此處坑,如果是服務器上一定要設置為IP地址,否則會重頭再來)

rscongfig={"_id":"rs0",members:[{_id:0,host:"localhost:27018"},{_id:1,host:"localhost:27019"},{_id:2,host:"localhost:27020"}]}

 

 

 

 

初始化該配置

rs.initiate(rscongfig)

回車如下圖,“ok”:1,無錯誤信息。為正確

 

 

 

看下當前節點是否為主節點

 

rs.status()查看當前副本集狀態

 

 

 

health:1   //1表明狀態是正常,0表明異常
state:1     // 1表明是primary,2表明是slave,即做備份的機器

到此副本集就搭建成功了。接下來是開啟身份驗證

11.創建用戶名

連接到27018,運行

use admin

定位到admin數據庫,在這裏創建用戶信息

db.createUser(
  {
    user: "root",
    pwd: "root",
    roles: [ { role: "root", db: "admin" } ]
  }
)  

12.找到主庫的配置文件 conf 開啟身份驗證,同時從庫也要開,配置好位置。

 

 

 

 

conf 配置好后,將服務重新啟動,然後客戶端重新連接后 如果查看等報錯的話就會提示需要權限,

然後轉到use admin

db.auth(“admin”,”admin”)輸入用戶名密碼

 返回1就是 成功。

然後登陸從節點進行登陸看一下是否需要提示。
如果都成功,可以寫入數據看一下複製集中是否有數據。

到此副本集身份驗證開啟說完了,下面說一下Springboot連接帶安全認證的複製集

application-dev.properties
spring.data.mongodb.uri=mongodb://admin:password@127.0.0.1:27018,127.0.0.1:27019,127.0.0.1:27020/ecis?authSource=admin&authMechanism=SCRAM-SHA-1&replicaSet=rs0& connectTimeoutMS=30000

//解釋
admin:password是用戶名密碼 @IP地址端口號 authSource=admin 用戶名存在的數據庫 authMechanism 不造啥意思 replicaSet 複製集名稱 connectTimeoutMS=30000連接時間

下面是navicat連接複製集方式

 

 添加主機名,端口號,點擊發現,可以查詢當前複製集中的端口服務。

 

終於寫完了,第一次寫,寫的不好,請見諒。

 

 

 

 

 

 

 

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

人臉識別技術原理與工程實踐(10個月人臉識別領域實戰總結)

1人臉識別應用場景(驗證)

我們先來看看人臉識別的幾個應用。第一個是蘋果的FACE ID,自從蘋果推出FaceID后,業界對人臉識別的應用好像信心大增,各種人臉識別的應用從此開始“野蠻生長”。

事實上,人臉識別技術在很多場景的應用確實可以提升認證效率,同時提升用戶體驗。前兩年,很多機場安檢都開始用上了人臉驗證;今年4月,很多一、二線城市的火車站也開通了“刷臉進站”的功能;北京的一些酒店開始使用人臉識別技術來做身份驗證。

 

2 人臉識別應用場景(識別)

我們再來看看幾個場景。

 

第一個是刷臉的自動售貨機。當我第一次看到這個機器的時候就有個疑問:”現在人臉識別算法已經做到萬無一失了嗎,認錯人,扣錯錢怎麼辦?”,後來才發現,其實關鍵不在於算法,產品設計才是最重要的。用過這個售貨機的人可能知道,第一次使用的時候,要求輸入手機號的后四位,這個看似簡單的產品設計,可以讓自動售貨機的誤識別率降低到億分之一,這樣底概率的條件下,誤識別帶來的損失完全可以忽略。同時這款自動售貨機還會提醒你,你的消費行為會綁定“芝麻信用”,想想有幾個人會為了一瓶“可樂”去影響自己的徵信記錄呢?

第二個是刷臉買咖啡,進入咖啡店后,在你選好喝什麼咖啡前,系統已經識別出站在點單台前的用戶是誰,並做好點單準備;

第三個是在人臉門禁系統。小夥伴們再已不用擔心忘記帶工卡了。人臉門禁對識別速度和準確度的要求是相對較高的,設備掛在門的側面牆也會影響體驗,增加產品設計和開發的難度。

 

3 “人臉驗證”還是“人臉識別”?

其實,前面兩頁的場景是有些區別的,不知道大家看出來了沒有。

第一個的場景,用戶實際提供了兩個信息,一是用戶的證件信息,比如身份證號碼,或APP賬號;另一個信息是用戶的現場照片;這類場景的目標實際上是:讓人臉識別系統驗證現場照片是否是證件所宣稱的那個人。我們把這類場景叫着“人臉驗證”

第二個的場景,用戶實際只提供的現場照片,需要人臉識別系統判斷照片上的人是誰。我們把這類場景叫着“人臉識別”

“人臉驗證”拿現場人臉跟用戶所宣稱的人臉做1比1的比較,而“人臉識別”是拿現場人臉跟後台註冊人臉庫中的所有人臉比較,是1比N的搜索。可以看出,兩種場景的技術原理一致,但是難度不同,第二頁場景的難度普遍比第一頁高得多。

 

4 人臉識別原理

計算機是怎麼識別人臉的呢?如果我們大家是人臉識別系統的設計者,我們應用怎樣來設計這個系統?

“把人臉區域從圖片中摳出來,然後拿摳出來的人臉跟事先註冊的人臉進行比較”,沒錯,就是這樣,說起來簡單,做又是另外一回事了,這裏又有兩個新的問題:

一是,“怎樣判斷圖片中是有沒有人臉?”,“怎樣知道人臉在圖片中的具體位置呢”,這是人臉檢測要解決的問題,人臉檢測告訴我們圖像中是否有人臉以及人臉的具體位置坐標。

二是,“我們怎樣比較兩個人臉是不是同一個人呢?”,一個像素一個像素比較嗎?光照,表情不一致,人臉偏轉都將導致該方法不可行。”人是怎樣判斷兩種照片中的人臉是不是同一個人的呢?”,我們是不是通過比較兩種照片上的人,是不是高鼻樑、大眼睛、瓜子臉這樣的面部特徵來做判斷的呢? 

我們來看一下計算機人臉識別的流程,首先是獲取輸入圖像,然後檢測圖像中是否有人臉,人臉的具體位置,然後判斷圖像的質量,比如圖像是否模糊,光照度是否足夠,然後檢測人臉偏轉的角度,旋轉人臉到一個正臉位置,再然後提取人臉特徵,比對人臉特徵,最後輸出識別結果。其中圖像質量檢測和人臉對齊這兩步是可選的步驟,根據具體應用場景來決定。

 

5 人臉檢測-經典方法

我們來看看經典的人臉檢測方法。

OpenCV和Dlib是兩個常用的算法庫。

OpenCV 中使用Haar Cascade來做人臉檢測,其實Haar Cascade可以檢測任何對象,比如人臉和臉上眼睛的位置。

DLIB中是使用方向梯度直方圖(Histogram of Oriented Gradient, HOG),即通過計算圖像局部區域的梯度方向直方圖來提取特徵,這種方法的本質在於梯度的統計信息,而梯度主要存在於邊緣的地方。

OpenCV和DLIB各自也有他們自己的基於深度學習的人臉檢測方法,使用起來非常簡單。從這幾種方法都可以做到CPU實時或GPU實時;經典的檢測方法對正臉的檢測效果比較好,深度學習的方法適應性更強,可以檢測各種角度的人臉

 

6 MTCNN人臉檢測

2016年提出來的MTCNN算法是目前公認比較好的人臉檢測算法是(Multi-task Cascaded Convolutional Networks),可以同時實現face detection和alignment,也就是人臉檢測和對齊。

這裏的對齊指的是檢測人臉眼睛、鼻子、嘴巴輪廓關鍵點LandMark。

MTCNN算法主要包含三個子網絡:P-Net (Proposal Network)、 R-Net(Refine Network)、O-Net(Output Network),這3個網絡按照由粗到細的方式處理輸入照片,每個網絡有3條支路用來分別做人臉分類、人臉框的回歸和人臉關鍵點定位

左上角,最開始對在多個尺度上對圖像做了resize,構成了圖像金字塔,然後這些不同尺度的圖像作為P、P、O網絡的輸入進行訓練,目的是為了可以檢測不同尺度的人臉

P-Net主要用來生成候選人臉框。 R-Net主要用來去除大量的非人臉框。O-Net和R-Net有點像,在R-NET基礎上增加了landmark位置的回歸,最終輸出包含一個或多個人臉框的位置信息和關鍵點信息

 

7 人臉特徵提取-經典方法

接下來,我們來看一下人臉特徵提取。經典的人臉特徵提取方法有EigenFace和FisherFace兩種。

EigenFace的思想是把人臉從像素空間變換到另一個空間,在另一個空間中做相似性的計算。EigenFace的空間變換方法是主成分分析PCA。這個方法90年代開始應用於人臉識別,因為主成分有人臉的形狀,所以也稱為“特徵臉”。

FisherFace是一種基於線性判別分析LDA(全稱Linear  Discriminant Analysis,)的人臉特徵提取算法, LDA和PCA都是利用特徵值排序找到主元的過程。LDA強調的是不同人臉的差異而不是照明條件、人臉表情和方向的變化。所以,Fisherface對人臉光照、人臉姿態變化的影響更不敏感。

 

8 人臉特徵提取-深度學習法

我們再來看看深度學習法。

利用神經網絡學習高度抽象的人臉特徵,然後將特徵表示為特徵向量,通過比較特徵向量之間的歐式距離來判定兩張照片是否是同一個人

 

9人臉特徵提取-深度學習法

總體思路是把人臉識別人物當分類任務來訓練,通過在損失函數上施加約束,讓相同的人的照片提取的特徵距離盡可能近,不是同一個人的照片的提取的特徵距離盡可能的遠

第一個Logit的地方輸出的是人臉的特徵向量,一般是128維或者512維,浮點向量。這個Logit前面是CNN分類網絡,這個Logit後面的部分是通過在損失函數上施加約束來訓練模型,讓模型區分相同的人和不同的人,後面的部分只需要在訓練階段計算,推理階段是不需要的。

 

10 人臉特徵提取-Metric Learning

基於深度學習的人臉特徵提取方法主要有兩類,一類Metric Learning,另一個是Additive Margin,這兩類方法的底層原理都是一樣的,就是“通過訓練網絡,讓相同人的特徵距離盡可能近,不同人的特徵距離盡可能的遠”。

孿生網絡和Triplet都屬於 Metric Learning這類方法。左邊孿生網絡顧名思義,就是有兩個網絡,一個網絡訓練讓相同的人之間的距離盡可能的近,另一個網絡讓不同人之間的距離盡可能遠。

右邊Triplet網絡是對孿生網絡的改進,將樣本組織為錨點、正樣本、負樣本的元組,通過訓練網絡讓錨點與正樣本之間的距離盡可能的近,錨點與負樣本之間的距離盡可能的遠,並且至少遠於一個閥值阿爾法。

 

11 人臉特徵提取-Additive Margin

Additive Margin這類方法主要是在分類模型的基礎,通過控制損失函數來達到“讓相同人的特徵距離盡可能近,讓不同人的特徵距離盡可能遠”的目標。

前面介紹的Metric Learning的方法最大的問題在於:需要重新組織樣本,模型最終能否收斂很大程度上取決於採樣是不是合理。基於Additive Margin的方法則不需要這一步,完全將人臉特徵提取當做分類任務來訓練,參數的設置也不需要太多trick,Additive Margin的方法大都是在損失函數上做文章。

最近幾年,這個類方法研究的比較多,上面這個圖中的softmax,Sphereface,Cosface,ArcFace都是Additive Margin方法,可以看出它都是通過改進損失函數,來實現“讓相同人的特徵距離盡可能近,讓不同人的特徵距離盡可能遠”這個目標

上面這個圖中,顏色相同的點表示一個人,不同的點表示不同的人,這個圖的展示比較形象,可以看出最後一個超球體的效果非常不錯

Additive Margin正在成為主流, InsightFace也屬於這一類,損失函數正是這個ArcFace。

大家可用思考一下,為什麼分類方法不能直接用於人臉識別?這裏不做詳細討論了。

 

12 人臉特徵提取-效果評估

我們再來看一下怎樣評估人臉特徵提取算法的效果。

主要是通過召回率和虛警率兩個指標來衡量。應用場景不同,這個兩個指標的設置也不同,一般情況下,在實踐中我們都要求在虛警率小於某個值(比如萬分之一)的條件下,召回率達到某個值(比如99%)。很多產品宣稱的識別準確率達到多少多少,很大可能是在公開數據集比如LFW上的測試結果。

公開的訓練數據集比較推薦的有:MS1MV2,這個數據集微軟前段事件已經宣布撤回不再提供下載,這個數據集大概有85000個不同的人的380萬張照片。另一個數據集是GLINT_ASIA,有9萬多人的280萬張照片。

 

13 工程實踐的挑戰及經驗分享

很多人都認為人臉識別應用,算法包打天下,事實並非如此,即使是最好的識別算法也扛不住像圖像質量差。圖像質量差、姿勢變化、面部形狀/紋理隨着時間推移的變化、遮擋這些問題,是我們在工程實踐中面臨的挑戰。

當然,大多數問題工程上我們有應對方法。比如圖像模糊,光照不足,我們可以先檢測圖像是否模糊,關照是否不足,質量不過關,就不把圖像送給識別算法。

再比如,用他人照片或視頻來欺騙人臉識別系統,目前已經有多種活體檢測方法來檢測並防止這種情況。

經過一段時間在人臉識別領域的摸爬滾打,個人認為影響用戶體驗的關鍵因素是識別快、識別准,識別快主要靠產品設計,識別准主要靠算法

拿人臉門禁來舉個例子,產品設計上可以在前端採集照片的時候過濾掉模糊、無人臉的照片,避免無效識別,同時前端在採集照片的時候,可以同時採集多張併發傳給後台,做併發識別,這些方法都可以大大提升識別通過的速度,提升用戶體驗。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

松下預計提高美國電池廠年產能以供特斯拉需求

日經亞洲評論28日報導,松下(Panasonic)汽車零件部門執行副總伊藤好生(Yoshio Ito)在受訪時表示,車用電池能量密度越來越高、處理的難度也跟著升高,松下不能將電池賣給沒有能力肩負起產品安全控管能力的電動車製造商。他說,從需求的角度來看、電動車電池銷售額要倍增不是件難事,但在考量合格工程師人數、土地、廠房以及主管機關許可執照等因素後松下決定不去追求不切實際的目標。

伊藤指出,松下已經決定將美國電池廠年產能提升至35 GWh、現階段並無進一步擴產的明確規劃。作為特斯拉(Tesla)的獨家電池供應商,松下的任務就是供應足夠的數量給客戶。他還提到,松下計畫開發雷達和聲納技術、聚焦自駕車市場中現有車商忽視的利基需求。

官網資料顯示,2020年特斯拉超級電池工廠(Gigafactory)的年產能將超過2013年全球鋰電池產能的總和。

華爾街日報7月15日報導,加州下議院已通過規模達30億美元的電動車購車退稅折扣法案,後續還得過上議院與州長Jerry Brown這兩關。

負責起草這項法案的舊金山民主黨籍議員Phil Ting表示,加州若想落實氣候變遷目標(2025年讓150萬輛零排放車輛上路)、勢必得想辦法給電動車產業打強心針才行。根據加州空氣資源局的統計,加州已有超過25萬輛零排放汽車(包括電動車)上路、佔美國約半數的比重。

特斯拉平價電動車「Model 3」售價為35,000美元起(不含獎勵計畫)、電池續航力為345公里。特斯拉在6月23日創下歷史收盤新高紀錄(383.45美元)、7月28日以335.07美元坐收。

(本文內容由授權使用。圖片出處:Tesla)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

特斯拉強敵現身!通用Bolt銷售奪冠、續航力勝Model S

特斯拉(Tesla)電動車出現勁敵,通用汽車(GM)的電動車「Bolt」,美國銷售創佳績,七月份超越特斯拉奪下冠軍寶座。

Inside EVs統計數據顯示,七月份美國電動車和油電混合車買氣,通用Bolt首度奪冠,共銷售1,917輛。排名第二是特斯拉電動休旅車Model X,銷售1,650輛。第三是豐田汽車(Toyota)的油電混合車Prius Prime,銷售1,645輛。第四是通用油電混合車Volt,銷售1,518輛。第五為特斯拉電動車Model S。

韓媒etnews 8日報導,特斯拉和豐田都採用日本製造的電池,通用汽車則使用南韓電池。通用的Bolt、Volt表現出色,使得南韓在美國的電池市佔率月增9%、至42%,不過仍不及日本電池在美國的58%市佔率。

Bolt價格實惠,被視為特斯拉平價車款Model 3的對手。特斯拉旗下有三款電動車,Model S和Model X為豪華車款,Model 3則走平價路線。Futurism 7日報導,Bolt價格只要Model S的一半,續航力卻擊敗Model S。

美國環境保護署估計,Model S 75D充電一次應該可跑416公里,Bolt應可跑383公里。不過美國權威雜誌《消費者報導》(Consumer Reports)實測發現,Bolt續航力高達402公里,Model S卻只有378公里。

Model 3喊出3.5萬美元價碼,不過該車款加價項目多,最終價格恐怕會高出不少。MarketWatch、Fortune、芝加哥論壇報報先前報導,價格仍是考驗Model 3買氣的一大重點。Model 3起跳價為3.5萬美元,選配項目極多。以電池而言,標準配備的電池充電一次可跑220英里(354公里)。若想換成310英里(499公里)的電池,需要加價9,000美元。想搭載輔助駕駛系統「Autopilot」需多付5,000美元。想要改換車體外觀顏色,也須加付1,000美元。

晨星汽車分析師David Whiston說,問題在於Model 3用戶到底願意付多少錢?3.5萬美元只是基本款,平均價大概落在4.2萬美元,若想買足選配約需6萬美元,這不是大眾市場汽車。

通用汽車搶得頭香,旗下「便宜又大碗(售價合理、續航力長)」電動車Chevrolet Bolt 2016年底開始交貨。Bolt續航力達238英里(383公里)、勝過特斯拉Model 3(售價35,000美元)的逾215英里。特斯拉預期Model 3將自2017年下半年起開始交貨、2018年公司整體年度交貨量將可從目前的10萬台跳升至50萬台。

Thomson Reuters報導,Bolt為通用汽車、南韓電池製造商LG Chem合作開發產品、建議零售價37,495美元起(註:最多可取得7,500美元的聯邦折抵稅額、扣除後入手價相當於29,995美元)。高層透露,通用汽車最終將推出自駕版Bolt。

(本文內容由授權使用。圖片出處:Bolt)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

政府帶頭衝,印度拚當全球電動車一哥

印度媒體Indiatimes報導,印度能源部長戈雅爾(Piyush Goyal)8月16日矢言全力推廣電動車,將像之前廣推節能LED的成功經驗一般,務求讓印度成為全球電動車的領導者。

印度政府以身作則,日前已經公開招標一萬輛電動車,將用以取代公家單位的汽柴油引擎車。除此之外,印度也計畫廣佈充電站,藉以提升電動車的方便性與市場需求。

印度為改善空氣污染,此前已對電動車展現旺盛企圖心。印度能源局六月初曾發下豪語,印度2030年將只賣電動車,希望還給印度人民一個乾淨的天空。

另外,按照印度日前發佈的「全國電動車計畫」(National Electric Mobility Mission Plan),2020年印度年度電動車/油電混合車銷售量將推升至600到700萬輛。

(本文內容由授權使用。圖片出處:pixabay CC0)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

Gogoro 正式進駐巴黎,首批400 部Gogoro 悠遊巴黎街頭

結合智慧能源與智慧交通的新創科技領導品牌Gogoro 睿能創意股份有限公司與其策略夥伴德國博世集團(BOSCH)子公司Coup 宣布,雙方在巴黎合作的Gogoro 智慧雙輪共享服務計畫17 日正式啟動,首批400 部Gogoro 已開始提供服務,並行駛於巴黎街頭。

Gogoro 與Coup 在巴黎的合作計畫引起巨大迴響,不但當地媒體踴躍報導給予極高的評價,消費者也熱烈回應早鳥計畫,紛紛開始預約。與柏林相同,這項共享計畫的價格相當平實,前30 分鐘僅需4 歐元,之後則每增加10 分鐘收取1 歐元。預估Gogoro 智慧雙輪共享服務計畫在巴黎受歡迎的程度將不亞於柏林。

Gogoro 執行長陸學森相當興奮的表示:「歐洲民眾有相當高的環境永續意識,消費者利用Gogoro 的Smartscooter 智慧雙輪進行都會通勤,不但節能減碳同時舒緩交通擁塞的壓力。Coup 的電動機車共享服務在柏林推出後廣受歡迎,現在在巴黎,同樣引起極大迴響。我們相信Gogoro 與Coup 帶動的電動機車共享服務熱潮將可以在更多城市發酵。Gogoro 和Coup 也會持續合作,專注於創新科技與永續交通之經營。」

另外在德國柏林,目前已經有1,000 台Smartscooter 智慧雙輪提供服務,未來前往柏林或巴黎,將可以考慮使用台灣之光的Gogoro 做為旅遊的交通工具之一。

(合作媒體:。圖片出處:科技新報)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

搶進電動車市場,電容量提高的鎂電池也要分杯羹

 

雖然鋰離子電池在市場上的聲勢居高不下,但安全性太招人質疑,現在又有一款主打更便宜、更安全的新電池要跟電動車市場分一杯羹了。一款由休士頓大學研究團隊開發的新型鎂電池,標榜電容量比商用鋰離子電池高出2 倍。

鎂電池最大的缺點在於充、放電過程中,充電性能會迅速衰退,過去由於鎂電池一直難找到能存儲大量鎂離子的陰極材料,不光打破氯化鎂鍵只為儲存鎂離子是很困難的技術,以這種方式產生的鎂離子在電池內移動速度也緩慢,種種原因都會導致電池效率低下,大好前程因此遭阻擋。目前,鎂電池主要供軍事通信、氣象測候儀、海難救生設備、高空雷達儀等設備使用。

現在,休士頓大學電機電子工程學系副教授Yan Yao 團隊在《自然通訊》雜誌發表最新研究,他們設計了奈米結構的電池陰極,讓新型鎂電池大大增加4 倍存儲容量。早期鎂電池儲存容量為100mAh / g,相比之下新電池可達400mAh / g,而一般的商業鋰離子電池陰極容量則約200mAh / g。

新型鎂電池將氯化鎂注入二硫化鈦的陰極材料以儲存能量,由於保留氯化鎂鍵沒有破壞,與傳統鎂電池相比,離子擴散速度比傳統材料快許多。Yan Yao 說,保留氯化鎂鍵可使陰極儲存的電荷翻倍,不過由於氯化鎂分子較大,所以關鍵就在擴大陰極材料的開口,以便容納更多氯化鎂。

於是,研究人員動手將二硫化鈦材料的開口撐大了300 倍──雖然還是很小,從0.57 奈米增加到1.8 奈米,但這樣便足夠讓氯化鎂分子通過。大容量的氯化鎂鍵有優異速度和循環性能,也為多價離子電池的未來開闢更多可能性。

高壓鋰離子電池雖然還是鞏固自己的市占率,但其成本高、內部結構易發生破壞導致起火等潛在問題,都使其隨時可能被更便宜、更安全的鎂電池、鋅電池等篡位。

新款鎂電池的電壓在1 伏特左右(鋰離子電池的電壓3到4 伏特),它在一定程度上受電壓限制,但研究人員仍期盼鎂電池的新設計能應用在更有價值的領域。Yan Yao 說:「我們的最高宗旨就是以更低價格製造更高能量電池,特別是在電動汽車領域,要和其他電池一較高下。」

(合作媒體:。首圖為鹼性電池,圖片出處:public domain CC0)  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

Hook原理–逆向開發

今天我們將繼續講解逆向開發工程另一個重要內容–Hook原理講解。Hook,可以中文譯為“掛鈎”或者“鈎子”,逆向開發中改變程序運行的一種技術。按照如下過程進行講解

  1. Hook概述
  2. Hook技術方式
  3. fishhook原理及實例
  4. 符號表查看函數名稱
  5. 總結

一、Hook概述

在逆向開發中是指改變程序運行流程的技術,通過Hook可以讓自己的代碼運行在別人的程序中。需要了解其Hook原理,這樣就能夠對惡意代碼攻擊進行有效的防護。

 

二、Hook技術方式

2.1 Method Swizzle方式

Method Swizzle 上次已經講到,是利用OC的Runtime的特性,去動態改變SEL(方法編號)與IMP(方法實現)的對應關係,達到OC方法調用流程更改的目的。也是主要用於OC方法。

2.2 Cydia Substrate方式

Cydia Substrate 原名叫做Mobile SubStrate,主要作用為針對C函數,OC函數以及函數的地址進行Hook操作。並且有個很大的優勢,Cydia Substrate 並不是僅僅是針對iOS設計,Andriod一樣也可以使用。

2.2.1

Cydia Substrate定義了一系列的函數和宏,底層調用了objc的runtime和fishHook來替代目標函數或者系統方法。

其中有兩個函數

  • MSHookMessageEx主要用於OC方法
void MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP result)
  • MSHookFunction主要用於C++和C函數
void MSHookFunction(voidfunction,void* replacement,void** p_original)

2.2.2 MobileLoader

MobileLoader主要用於加載第三方dylib運行的應用程序中。啟動時MobileLoader會根據指定的第三方動態庫加載進去,第三方動態庫也是我們寫的破解程序。

2.2.3 safe mode

破解程序的本質在於dylib,寄生於別人程序進程中。但是系統進程一旦出現錯誤,可能會導致整個進程崩潰,也可能會導致iOS程序崩潰。在Cydia Substrate 中引入了安全模式,如果一旦錯誤,三方的dylib會被禁用,便於查錯和修復。

2.3 fishHook

fishHook是Facebook提供一種動態修改鏈接Mach-O文件的工具。此利用Mach-O文件加載原理,通過修改非懶加載和懶加載兩個表的指針達到C函數的Hook的目的。

今天我們主要講解第三種方式fishHook達到更改程序的目的。

 

三、fishhook原理及實例

3.1 概述

fishhook的源碼地址為

fishhook的主要方法有兩個還有一個結構體

查看代碼結構為,將紅色圈起來部分移入到代碼中,即可使用fishhook來hook代碼。

 

 3.2 實例

3.2.1 Demo1實例1

// rebinding 結構體的定義 // struct rebinding { // const char *name; // 需要 HOOK 的函數名稱,字符串 // void *replacement; // 替換的新函數(函數指針,也就是函數名稱) // void **replaced; // 保存原始函數指針變量/地址的指針(它是一個二級指針!) // }; // C 語言傳參是值/址傳遞的,把它的值/址穿過去,就可以在函數內部修改函數指針變量的值

- (void)viewDidLoad {
    [super viewDidLoad];
     NSLog(@"123"); //rebinding結構體
    struct rebinding nslog;
    nslog.name = "NSLog";// 函數名稱
    nslog.replacement = myNslog; // 新的函數指針
    nslog.replaced = (void *)&sys_nslog;// 保存原始函數地址的變量的指針
    //rebinding結構體數組
    struct rebinding rebs[1] = {nslog};
    /**
     * 存放rebinding結構體的數組
     * 數組的長度
     */
    rebind_symbols(rebs, 1);
}
//---------------------------------更改NSLog-----------
//函數指針,用來保存原始的函數地址 (C 語言語法,函數指針類型變量)
static void(*sys_nslog)(NSString * format,...);
//定義一個新的函數
void myNslog(NSString * format,...){
    format = [format stringByAppendingString:@"勾上了!\n"];
    //調用原始的
    sys_nslog(format);
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    NSLog(@"點擊了屏幕!!");
}

上面的代碼運行結果如下:

3.2.2 Demo2實例2

void func(const char * str){
    NSLog(@"%s",str);
}

- (void)viewDidLoad {
    [super viewDidLoad];
    //rebinding結構體
    struct rebinding nslog;
    nslog.name = "func";
    nslog.replacement = new_func;
    nslog.replaced = (void *)&old_func;
    //rebinding結構體數組
    struct rebinding rebs[1] = {nslog};
    /**
     * 存放rebinding結構體的數組
     * 數組的長度
     */
    rebind_symbols(rebs, 1);
}
//---------------------------------更改NSLog-----------
//函數指針
static void(*old_func)(const char * str);
//定義一個新的函數
void new_func(const char * str){
      NSLog(@"%s + 1",str);
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    func("哈哈");
}

運行結果如下:

從上面可以看出自定義的交換方法為什麼交換不了呢?首先可以肯定的是代碼是OK的,下面我們講解原理,為什麼自定義的方法不行呢?

 

 3.3 原理探究

Mach-O文件是如何加載的?

Dyld工具動態加載,加載MachO文件完成后,開始加載依賴的動態庫,也就是通過上篇博客的image List 可看到相關的類庫。

PIC(Promrammable Interrupt Controller)位置代碼獨立,由外設發出中斷請求需要中斷控制器來處理。

Mach-O文件內部調用系統函數時:

  • Mach-O _data段建立了一個指針(也就是符號,實現指向內部的函數調用,指向了外部的函數地址),指向了外部函數(dyld),可讀可寫,當Mach-O被加載進去,就會指向所指的函數。
  • Dyld會動態的綁定,將Mach-O中的data 段中指針指向了外部的函數,也是Dyld為什麼叫做動態綁定的原因。

這也回答了上面的問題,為什麼內部/自定義的函數不能修改,只能修改Mach-O文件的外部函數,如果是另外一個動態庫或者需要動態符號綁定的就可以(符號表中能找到才可以實現)

 

下面我們是真實查看內容,通過實例

利用第一個Demo來測試,運行起來,然後查看可執行文件,通過MachoView工具

 

從圖2看出offset偏移地址為3028,也就是NSLog函數文件的偏移地址,懶加載此表時在Mach-O文件偏移地址+函數偏移的地址。

下面以Demo1查看,在Demo1打斷點,查看Mach-O函數偏移地址,通過指令image list 第一個就是Mach-O內容和地址(本人上篇博客地址即可)

Mach-O在內存的偏移地址也就是Mach-O的真實地址,發現為 0x000000010a9c5000

通過上面紅色加重算法,計算Mach-O文件Data段的函數指針

發現執行完只有就會被綁定。NSLog函數文件就會被綁定。

下面再看一下,對於屏幕點擊的,hook如下

前提是我們去除ViewDidLoad方法裏面的NSLog(@“123”)這句代碼,運行代碼,最後將斷點斷在touchesBegan裏面,此時開始看地址和內容

截圖的前兩次打印是程序運行時,但是未曾點擊touchesBegan,后兩次是點擊屏幕時斷點進入到了裏面,再看內容,打印的對象是NSLog還是myNslog,通過上面發現是myNslog,說明Hook成功。

通過上面可看出,fishhook能夠Hook c函數,是因為Mach-O文件特點,PIC位置代碼獨立造就了靜態語言C也有動態的部分,之後通過Dyld進行動態綁定的時機,在這其中我們就可以做手腳,替換自定義的方法。

fishhook是根據方法字符串的名字“NSLog”,它是怎麼找到的呢?下面將講解利用符號表查看函數名稱字符串。

 

四、符號表查看函數名稱

 再次查看Mach-O文件,查看懶加載表中的NSLog函數

懶加載表是和動態符號表是一一對應關係,通過上面發現NSLog函數時第一個,而對應的Dynamic Symbol table也是第一個,打開Dynamic Symbol table

查看Dynamic Symbol Table 第一個也是NSLog,查看Data值為7A,對應的十進製為122,然後到Symbols Table裏面查看122,如下:

 

查看Symbols Table的data值為0000009B,然後在String Table Index去看函數偏移值為0000009B的內容,如下:

 

 為什麼選擇00004F94查看NSLog呢,我們從上面得知Symbols Table的data值為0000009B,然後加上String Table的函數第一個地址為00004F04,然後將0000009B + 00004F04 = 0X4F9F,最後看00004F94裡面包含了0X4F9F,藍色內容看出是NSLog內容,也就是找到啦。完美!!!

以上過程可以在fishhook中github上有說明圖:

 

上面的說明圖也就是通過符號表查看函數名稱以及反過來也可以逆查的過程。配上說明圖,方便大家熟悉流程。

 

五、總結

上面講述了Hook的幾種技術方式以及fishhook的原理探究,以及如何讓別人的app實現自己的代碼。下面我們對此總結一下,寫了一個本篇博客的整個過程便於大家整理,希望對大家有所幫助加深理解。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

GoStation電池交換站突破400座,電池交換成為市場主流

 

結合智慧能源與智慧交通的新創科技品牌Gogoro(睿能創意股份有限公司)7 日公布全台建置與營運中的GoStation 電池交換站已達400 站,再度創造新的里程碑。從2015 年7 月至今,Gogoro 在基隆到屏東的台灣西半部地區,平均每1.8 天即新增一座電池交換站,最近一個月,每日提供將近4 萬名車主接近17,000 顆的電池交換服務,電池交換服務已經成為台灣消費者購買電動機車時的首要選擇。

自從Gogoro 於2015 年在台北市設立首座電池交換站以來,在短短兩年多的時間,建置了400 座電池交換站,廣布於基隆到屏東的各個縣市,推升Gogoro 電動機車市佔率至85.1%,並穩居台灣機車市場第四名的寶座。在今年7 月開通雲嘉地區電池交換站後,暢騎台灣西半部,不再是夢想。同時六都的電池交換站建置更來到一公里一站。

Gogoro 行銷總監陳彥揚說:「我們會依據人口密集度、車輛密極度以及道路的重要性來建置及調度電池交換站。根據車主換電的大數據分析,換電最密集的電池交換站位於Gogoro 永和中正店,而換電的尖峰時刻不外乎是上、下班的時間。有趣的是,雖然全台已經有將近400 座電池交換站,但每名消費者平均只會造訪其中的3-4 站來更換電池。證明Gogoro 能源網路的大數據分析,能計算出消費者換電池的使用行為模式,滿足車主們的需求。」

走在環保、綠能尖端的Gogoro,目前共建置了兩座太陽能換電站,分別是八里公兒四電池交換站和Gogoro 師大和平店站,這兩站設有物聯網智慧平台,透過分析供電情況的螢幕,說明了包括減少碳排量、減少樹木砍伐面積、綠能總儲電量、城市電網和太陽能發電量等訊息,讓每名換電的民眾,清楚的知道,自己對環境的貢獻度。

陳彥揚說:「Gogoro 致力發展潔淨的智慧能源,希望具備能源調度能力的智慧電網,能成為城市的電力調節樞紐,以促成電力平衡。對於Gogoro 車主而言,Gogoro 不再僅是都會的通勤工具,而是更進一步深入使用者的生活,同時讓生活環境更環保、更健康。」

Gogoro 目前擁有近4 萬名車主,總共累積超過570 萬次的電池交換,總里程數超過1 億100 公里,已經替地球減少將近840 萬公斤的二氧化碳排放,隨著未來再生能源比例逐漸提升,Gogoro 的車主們將更對地球與環境產生更多正面的影響力。而Gogoro 更會透過大數據進行科學的規劃,以調控電池供應,未來,即便新增的萬名車主同步上路,也能確保能源及電池的調配無虞。

(合作媒體:。圖片出處:科技新報)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益