【Tensorflow】卷積神經網絡實現藝術風格化通過Vgg16實現

卷積神經網絡實現藝術風格化

基于卷積神經網絡實現圖片風格的遷移,可以用于大學生畢業設計基于python,深度學習,tensorflow卷積神經網絡, 通過Vgg16實現,一幅圖片內容特征的基礎上添加另一幅圖片的風格特征從而生成一幅新的圖片。在卷積模型訓練中,通過輸入固定的圖片來調整網絡的參數從而達到利用圖片訓練網絡的目的。而在生成特定風格圖片時,固定已有的網絡參數不變,調整圖片從而使圖片向目標風格轉化。在內容風格轉換時,調整圖像的像素值,使其向目標圖片在卷積網絡輸出的內容特征靠攏。在風格特征計算時,通過多個神經元的輸出兩兩之間作內積求和得到Gram矩陣,然后對G矩陣做差求均值得到風格的損失函數。

示例代碼:

import time
import numpy as np
import tensorflow as tf
from PIL import Image
from keras import backend
from keras.models import Model
from keras.applications.vgg16 import VGG16
from scipy.optimize import fmin_l_bfgs_b
from scipy.misc import imsave 

加載和預處理內容和樣式圖像

加載內容和樣式圖像,注意,我們正在處理的內容圖像質量不是特別高,但是在這個過程結束時我們將得到的輸出看起來仍然非常好

height = 512
width = 512
content_image_path = 'images/elephant.jpg'
content_image = Image.open(content_image_path)
content_image = content_image.resize((height, width))
content_image

在這里插入圖片描述

style_image_path = 'images/styles/wave.jpg'
style_image = Image.open(style_image_path)
style_image = style_image.resize((height, width))
style_image

在這里插入圖片描述

然后,我們將這些圖像轉換成適合于數值處理的形式。
特別注意,我們添加了另一個維度(高度x寬度x 3維度)

以便我們可以稍后將這兩個圖像的表示連接到一個公共數據結構中。

content_array = np.asarray(content_image, dtype='float32')
content_array = np.expand_dims(content_array, axis=0)
print(content_array.shape)style_array = np.asarray(style_image, dtype='float32')
style_array = np.expand_dims(style_array, axis=0)
print(style_array.shape)
(1, 512, 512, 3)
(1, 512, 512, 3)

我們需要執行兩個轉換:

1.從每個像素中減去平均RGB值 (具體原因可查論文此處原因暫時省略)

2.將多維數組的順序從RGB翻轉到BGR(本文中使用的順序)。

content_array[:, :, :, 0] -= 103.939
content_array[:, :, :, 1] -= 116.779
content_array[:, :, :, 2] -= 123.68
content_array = content_array[:, :, :, ::-1]style_array[:, :, :, 0] -= 103.939
style_array[:, :, :, 1] -= 116.779
style_array[:, :, :, 2] -= 123.68
style_array = style_array[:, :, :, ::-1]

現在我們可以使用這些數組在Keras的后端(TensorFlow圖)中定義變量了。
我們還引入了一個占位符變量來存儲組合圖像,
該圖像在合并樣式圖像的樣式時保留了內容圖像的內容。

content_image = backend.variable(content_array)
style_image = backend.variable(style_array)
combination_image = backend.placeholder((1, height, width, 3))
NOISE_RATIO = 0.6
def generate_noise_image(content_image, noise_ratio = NOISE_RATIO):"""Returns a noise image intermixed with the content image at a certain ratio."""noise_image = np.random.uniform(-20, 20,(1, height, width, 3)).astype('float32')# White noise image from the content representation. Take a weighted average# of the valuesinput_image = noise_image * noise_ratio + content_image * (1 - noise_ratio)return input_image
content_image = tf.Variable(content_array,dtype=tf.float32)style_image = tf.Variable(style_array,dtype=tf.float32)# combination_image = tf.placeholder(dtype=tf.float32,shape = (1,height,width,3))combination_image = tf.Variable(initial_value=generate_noise_image(content_image))

最后,我們將所有這些圖像數據連接到一個張量中,
該張量適合用Keras’VGG16模型進行處理。

input_tensor = backend.concatenate([content_image,style_image,combination_image], axis=0) #作用 將兩個變量和占位符數據集成
input_tensor = tf.concat([content_image,style_image,combination_image],axis = 0)
input_tensor

重新使用預先訓練的圖像分類模型來定義損失函數

由于我們對分類問題不感興趣,因此不需要完全連接的層或最終的softmax分類器。我們只需要下表中用綠色標記的那部分型號。

在這里插入圖片描述
對于我們來說,訪問這個被截斷的模型是很簡單的,因為Keras附帶了一組預先訓練的模型,包括我們感興趣的VGG16模型。注意,通過在下面的代碼中設置“include_top=False”,我們不包括任何完全連接的層。

model = VGG16(input_tensor=input_tensor, weights='imagenet',include_top=False)
<keras.engine.training.Model at 0x267f261f208>

從上表可以看出,我們使用的模型有很多層。對于這些層,Keras有自己的名稱。讓我們列出這些名稱,以便以后可以方便地引用各個層。

layers = dict([(layer.name, layer.output) for layer in model.layers])
layers
讀取本地模型
import scipy as scipydef load_vgg_model(path):"""Returns a model for the purpose of 'painting' the picture.Takes only the convolution layer weights and wrap using the TensorFlowConv2d, Relu and AveragePooling layer. VGG actually uses maxpool butthe paper indicates that using AveragePooling yields better results.The last few fully connected layers are not used.Here is the detailed configuration of the VGG model:0 is conv1_1 (3, 3, 3, 64)1 is relu2 is conv1_2 (3, 3, 64, 64)3 is relu    4 is maxpool5 is conv2_1 (3, 3, 64, 128)6 is relu7 is conv2_2 (3, 3, 128, 128)8 is relu9 is maxpool10 is conv3_1 (3, 3, 128, 256)11 is relu12 is conv3_2 (3, 3, 256, 256)13 is relu14 is conv3_3 (3, 3, 256, 256)15 is relu16 is maxpool17 is conv4_1 (3, 3, 256, 512)18 is relu19 is conv4_2 (3, 3, 512, 512)20 is relu21 is conv4_3 (3, 3, 512, 512)22 is relu23 is maxpool24 is conv5_1 (3, 3, 512, 512)25 is relu26 is conv5_2 (3, 3, 512, 512)27 is relu28 is conv5_3 (3, 3, 512, 512)29 is relu30 is maxpool31 is fullyconnected (7, 7, 512, 4096)32 is relu33 is fullyconnected (1, 1, 4096, 4096)34 is relu35 is fullyconnected (1, 1, 4096, 1000)36 is softmax"""vgg = scipy.io.loadmat(path)vgg_layers = vgg['layers']def _weights(layer, expected_layer_name):"""Return the weights and bias from the VGG model for a given layer.layers[0][0][0][0][2][0][0]"""W = vgg_layers[0][layer][0][0][2][0][0]b = vgg_layers[0][layer][0][0][2][0][1]layer_name = vgg_layers[0][layer][0][0][0]assert layer_name == expected_layer_namereturn W, bdef _relu(conv2d_layer):"""Return the RELU function wrapped over a TensorFlow layer. Expects aConv2d layer input."""return tf.nn.relu(conv2d_layer)def _conv2d(prev_layer, layer, layer_name):"""Return the Conv2D layer using the weights, biases from the VGGmodel at 'layer'."""W, b = _weights(layer, layer_name)W = tf.constant(W)b = tf.constant(np.reshape(b, (b.size)))return tf.nn.conv2d(prev_layer, filter=W, strides=[1, 1, 1, 1], padding='SAME') + bdef _conv2d_relu(prev_layer, layer, layer_name):"""Return the Conv2D + RELU layer using the weights, biases from the VGGmodel at 'layer'."""return _relu(_conv2d(prev_layer, layer, layer_name))#     def _avgpool(prev_layer):
#         """
#         Return the AveragePooling layer.#         return tf.nn.avg_pool(prev_layer, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')def _avgpool(prev_layer):return tf.nn.max_pool(prev_layer,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')# Constructs the graph model.graph = {}graph['input']   = input_tensorgraph['conv1_1']  = _conv2d_relu(graph['input'], 0, 'conv1_1')graph['conv1_2']  = _conv2d_relu(graph['conv1_1'], 2, 'conv1_2')graph['_maxpool1'] = _avgpool(graph['conv1_2'])graph['conv2_1']  = _conv2d_relu(graph['_maxpool1'], 5, 'conv2_1')graph['conv2_2']  = _conv2d_relu(graph['conv2_1'], 7, 'conv2_2')graph['_maxpool2'] = _avgpool(graph['conv2_2'])graph['conv3_1']  = _conv2d_relu(graph['_maxpool2'], 10, 'conv3_1')graph['conv3_2']  = _conv2d_relu(graph['conv3_1'], 12, 'conv3_2')graph['conv3_3']  = _conv2d_relu(graph['conv3_2'], 14, 'conv3_3')graph['_maxpool3'] = _avgpool(graph['conv3_3'])graph['conv4_1']  = _conv2d_relu(graph['_maxpool3'], 17, 'conv4_1')graph['conv4_2']  = _conv2d_relu(graph['conv4_1'], 19, 'conv4_2')graph['conv4_3']  = _conv2d_relu(graph['conv4_2'], 21, 'conv4_3')graph['_maxpool4'] = _avgpool(graph['conv4_3'])graph['conv5_1']  = _conv2d_relu(graph['_maxpool4'], 24, 'conv5_1')graph['conv5_2']  = _conv2d_relu(graph['conv5_1'], 26, 'conv5_2')graph['conv5_3']  = _conv2d_relu(graph['conv5_2'], 28, 'conv5_3')graph['_maxpool5'] = _avgpool(graph['conv5_3'])return graph
from scipy import io
import tensorflow as tf
model = load_vgg_model('./imagenet-vgg-verydeep-16.mat')

如果你盯著上面的單子看,你會相信我們已經把所有我們想要的東西都放在桌子上了(綠色的單元格)。還要注意,因為我們為Keras提供了一個具體的輸入張量,所以各種張量流張量得到了定義良好的形狀。


風格轉換問題可以作為一個優化問題

其中我們希望最小化的損失函數可以分解為三個不同的部分:內容損失風格損失總變化損失

這些項的相對重要性由一組標量權重決定。這些都是任意的,但是在經過相當多的實驗之后選擇了下面的集合,以找到一個生成對我來說美觀的輸出的集合。

content_weight = 0.025
style_weight = 5.0
total_variation_weight = 1.0

我們現在將使用模型的特定層提供的特征空間來定義這三個損失函數。我們首先將總損失初始化為0,然后分階段將其相加。

loss = tf.Variable(0.)
loss

content_loss

content_loss 是內容的特征表示與組合圖像之間的(縮放,平方)歐氏距離。

def content_loss(content, combination):return tf.reduce_sum(tf.square(combination - content))layer_features = model['conv2_2']
content_image_features = layer_features[0, :, :, :]
combination_features = layer_features[2, :, :, :]loss += content_weight * content_loss(content_image_features,combination_features)

風格損失

這就是事情開始變得有點復雜的地方。

對于樣式丟失,我們首先定義一個稱為Gram matrix的東西。該矩陣的項與對應特征集的協方差成正比,從而捕獲關于哪些特征傾向于一起激活的信息。通過只捕獲圖像中的這些聚合統計信息,它們對圖像中對象的特定排列是盲目的。這使他們能夠捕獲與內容無關的樣式信息。(這根本不是微不足道的,我指的是[試圖解釋這個想法的論文] 。

通過對特征空間進行適當的重構并取外積,可以有效地計算出Gram矩陣。

def gram_matrix(x):features = backend.batch_flatten(backend.permute_dimensions(x, (2, 0, 1)))gram = backend.dot(features, backend.transpose(features))return gram
#也可用tf的方法 不使用kears的后端
# def gram_matrix(x):
#     ret = tf.transpose(x, (2, 0, 1))
#     features = tf.reshape(ret,[ret.shape[0],-1])
#     gram = tf.matmul(features,tf.transpose(features))
#     return gram

樣式損失是樣式和組合圖像的Gram矩陣之間的差的(縮放,平方)Frobenius范數。

同樣,在下面的代碼中,我選擇使用Johnson等人定義的圖層中的樣式特性。(2016)而不是蓋蒂等人。(2015)因為我覺得最終的結果更美觀。我鼓勵你嘗試這些選擇,以看到不同的結果。

def style_loss(style, combination):S = gram_matrix(style)C = gram_matrix(combination)channels = 3size = height * widthreturn tf.reduce_sum(tf.square(S - C)) / (4. * (channels ** 2) * (size ** 2))feature_layers = ['conv1_2', 'conv2_2','conv3_3', 'conv4_3','conv5_3']
for layer_name in feature_layers:layer_features = model[layer_name]style_features = layer_features[1, :, :, :]combination_features = layer_features[2, :, :, :]sl = style_loss(style_features, combination_features)loss += (style_weight / len(feature_layers)) * sl

總變化損失

現在我們回到了更簡單的基礎上。

如果您只使用我們目前介紹的兩個損失項(樣式和內容)來解決優化問題,您會發現輸出非常嘈雜。因此,我們增加了另一個術語,稱為[總變化損失](一個正則化項),它鼓勵空間平滑。

您可以嘗試減少“總變化”權重,并播放生成圖像的噪聲級別。

combination_image
def total_variation_loss(x):a = tf.square(x[:, :height-1, :width-1, :] - x[:, 1:, :width-1, :])b = tf.square(x[:, :height-1, :width-1, :] - x[:, :height-1, 1:, :])return tf.reduce_sum(tf.pow(a + b, 1.25))loss += total_variation_weight * total_variation_loss(combination_image) 
optimizer = tf.train.AdamOptimizer(0.001).minimize(loss)
optimizer

定義所需的梯度并解決優化問題

現在,我們已經對輸入圖像進行了處理,并定義了了損失函數 calculators,
剩下的工作就是定義相對于組合圖像的總損失的梯度,
并使用這些梯度對組合圖像進行迭代改進,以最小化損失。

grads = backend.gradients(loss, combination_image)
grads

然后,我們需要定義一個“Evaluator”類,
它通過兩個單獨的函數“loss”和“grads”檢索丟失和漸變。

之所以這樣做,是因為“scipy.optimize”需要單獨的函數來處理損失和梯度,但是單獨計算它們將是低效的。

outputs = [loss]
outputs += grads
f_outputs = backend.function([combination_image], outputs)def eval_loss_and_grads(x):x = x.reshape((1, height, width, 3))outs = f_outputs([x])loss_value = outs[0]grad_values = outs[1].flatten().astype('float64')return loss_value, grad_valuesclass Evaluator(object):def __init__(self):self.loss_value = Noneself.grads_values = Nonedef loss(self, x):assert self.loss_value is Noneloss_value, grad_values = eval_loss_and_grads(x)self.loss_value = loss_valueself.grad_values = grad_valuesreturn self.loss_valuedef grads(self, x):assert self.loss_value is not Nonegrad_values = np.copy(self.grad_values)self.loss_value = Noneself.grad_values = Nonereturn grad_valuesevaluator = Evaluator()

現在我們終于可以解決我們的優化問題了。這個組合圖像的生命開始于一個隨機的(有效的)像素集合,我們使用[L-BFGS]算法(一個比標準梯度下降更快收斂的準牛頓算法)迭代改進它。

我在2次迭代之后就停止了,因為時間問題,可以定義十次左右,效果較好損失可以自己觀察。

evaluator.grads

x = np.random.uniform(0, 255, (1, height, width, 3)) - 128.iterations = 2for i in range(iterations):print('Start of iteration', i)start_time = time.time()x, min_val, info = fmin_l_bfgs_b(evaluator.loss, x.flatten(),fprime=evaluator.grads, maxfun=20)print('Current loss value:', min_val)end_time = time.time()print('Iteration %d completed in %ds' % (i, end_time - start_time))

Start of iteration 0
Current loss value: 73757336000.0
Iteration 0 completed in 217s
Start of iteration 1
Current loss value: 36524343000.0
Iteration 1 completed in 196s

效果圖在這里插入圖片描述

總結

盡管這段代碼的輸出非常漂亮,但用來生成它的過程非常緩慢。
不管你如何加速這個算法(使用gpu和創造性的黑客),
它仍然是一個相對昂貴的問題來解決。
這是因為我們每次想要生成圖像時都在解決一個完整的優化問題。


PS:公眾號內回復 :Python,即可獲取最新最全學習資源!

    破解專業版pycharm參考博客www.wakemeupnow.cn公眾號:劉旺學長

內容詳細:【個人分享】今年最新最全的Python學習資料匯總!!!

在這里插入圖片描述
以上,便是今天的分享,希望大家喜歡,
覺得內容不錯的,歡迎點擊分享支持,謝謝各位。

在這里插入圖片描述
單純分享,無任何利益相關!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455641.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455641.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455641.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

抗誤碼技術

抗誤碼技術&#xff1a; 視頻傳輸過程中的錯誤是不可避免的&#xff0c;抗誤碼技術歷來都足視頻領域一個研究的熱點。H264標準繼承r以前視頻編碼標準中某些優秀的錯誤恢復工具&#xff0c;同時也改進和創新了多種錯誤恢復丁具。這些錯誤恢復的工具主要有&#xff1a;參數集、數…

Linux統計文件行數、字數、字節數

2019獨角獸企業重金招聘Python工程師標準>>> 語法&#xff1a;wc [選項] 文件 說明&#xff1a;該命令統計給定文件中的字節數、字數、行數。如果沒有給出文件名&#xff0c;則從標準輸入讀取。wc同時也給出所有指定文件的總統計數。字是由空格字符區分開的最大字符…

tkinter中鼠標與鍵盤事件

tkinter中鼠標與鍵盤事件&#xff08;十五&#xff09; 本文轉自Tynam Yang的博客園 import tkinterwuya tkinter.Tk() wuya.title("wuya") wuya.geometry("300x2001020")bt tkinter.Button(wuya,text鼠標進入打印) bt.pack()def func(event):print(鼠…

html解析のBeautifulSoup

引子&#xff1a; 使用python爬蟲對爬取網頁進行解析的時候&#xff0c;如果使用正則表達式&#xff0c;有很多局限&#xff0c;比如標簽中出現換行&#xff0c;或者標簽的格式不規范&#xff0c;都有可能出現取不到數據&#xff0c;BeautifulSoup作為一個專門處理html格式的py…

【Tensorflow】人臉128個關鍵點識別基于卷積神經網絡實現

引言&#xff1a; 卷積神經網絡 卷積神經網絡最早是為了解決圖像識別的問題,現在也用在時間序列數據和文本數據處理當中,卷積神經網絡對于數據特征的提取不用額外進行,在對網絡的訓練的過程當中,網絡會自動提取主要的特征.卷積神經網絡直接用原始圖像的全部像素作為輸入,但是內…

python 爬蟲 包_python爬蟲學習之路-抓包分析

利用瀏覽器抓包&#xff0c;是爬蟲中的很實用的技能。在爬蟲編程之前&#xff0c;我們要對抓取的目標頁面有所了解&#xff0c;比如瀏覽器的這個請求這個頁面中間都經歷了什么&#xff0c;數據是怎么發送和返回的。 抓包的作用 我把抓包分析的作用簡單列一下&#xff1a; 分析請…

幀間EC原理和過程

出錯的宏塊&#xff08;圖中灰色表示&#xff09;根據上、下、左、右四個方向相鄰宏塊的不同分割情況及預測類型進行插值。將最后的結果中進行比較&#xff0c;選取邊界像素差值之和最小者為最優的EC方案。其步驟為&#xff1a; 1、判斷相鄰宏塊左上角8*8塊的預測模式是否大于R…

Maven依賴的是本地工程還是倉庫jar包?

相信大家都碰見過maven配置的依賴或者是jar包或者是工程&#xff0c;在開發的過程當中&#xff0c;我們當然需要引入的是工程&#xff0c;這樣查看maven依賴的文件的時候&#xff0c;就能直接查看到源碼。 一、本地工程依賴 舉個例子&#xff0c;其架構如下所示&#xff08;以下…

關于django新版本無法使用MySQL數據庫的問題

關于django新版本無法使用MySQL數據庫的問題 參考這里 稍微記錄下Django2.2使用MariaDB和MySQL遇到的坑 現在演示一下整個流程吧 1.創建項目和應用 PS&#xff1a;你也可以使用PyCharm直接創建項目 2.注冊應用 先把剛剛創建的應用添加進去 3.配置MySQL或者MariaDB 4.PyMySQL替…

[轉]Spring事務tx:annotation-driven/

在使用SpringMVC的時候&#xff0c;配置文件中我們經常看到 annotation-driven 這樣的注解&#xff0c;其含義就是支持注解&#xff0c;一般根據前綴 tx、mvc 等也能很直白的理解出來分別的作用。<tx:annotation-driven/> 就是支持事務注解的&#xff08;Transactional&a…

【自動化測試】整理各種測試開發工具!持續更新

收集和整理各種測試工具&#xff0c;自動化測試工具&#xff0c;自動化測試框架&#xff0c;覺得有幫助記得三連一下。歡迎提交各類測試工具到本博客。 通用測試框架 JUnit: 最著名的xUnit類的單元測試框架&#xff0c;但是不僅僅可以做單元測試。TestNG: 更強大的Java測試框架…

python連接sql數據庫_python連接sql server數據庫實現增刪改查

簡述 python連接微軟的sql server數據庫用的第三方模塊叫做pymssql&#xff08;document&#xff1a;http://www.pymssql.org/en/stable/index.html&#xff09;。在官方文檔可以看到&#xff0c;pymssql是基于_mssql模塊做的封裝&#xff0c;是為了遵守python的DBAPI規范接口.…

es5.0 安裝head插件

es5.0的安裝和之前的版本有些區別,我的電腦用plugin install 沒成功, 查了一下資料,說是可以用grunt進行安裝,啟動; 1,先安裝grunt: grunt是一個很方便的構建工具&#xff0c;可以進行打包壓縮、測試、執行等等的工作&#xff0c;5.0里的head插件就是通過grunt啟動的。 npm ins…

Django后臺項目之用戶管理功能開發流程

項目功能開發流程 1 先寫列表頁&#xff08;加載出來數據就行&#xff09; ob User_vip.objects.filter(is_del004001).order_by(-cts)2 寫添加功能 2.1 創建addOrDoadd視圖方法 2.2 添加訪問addOrDoadd的路由 2.3 在index.html頁面吧添加的按鈕的鏈接不全 <a style&…

套接字 資料查閱

(3)套接字(socket) 一個完整的網絡應用程序包括客戶端和服務器兩個部分。網間通信進程需要由兩個進程組成&#xff0c;并且只能用同一種協議。也就是說&#xff0c;不能在通信的一端使用TCP協議&#xff0c;而另一端則用UDP協議。一個完整的網絡通信需要一個五元組來標識…

linux mysql安裝_Linux下安裝mysql服務(超詳細)

Mysql數據庫的安裝對于開發者來說&#xff0c;是我們必然會面對的問題&#xff0c;它的安裝過程其實并不復雜&#xff0c;并且網絡上的安裝教程也非常多&#xff0c;但是對于新手來說&#xff0c;各種不同形式的安裝教程&#xff0c;又給新手們帶來了要選擇哪種方式進行安裝的難…

dash 和 bash 切換

#先看看是用的哪個 shellls -al /bin/sh #如果是dash&#xff0c;切換到bashsudo ln -fs /bin/bash /bin/sh轉載于:https://www.cnblogs.com/abolide/p/6874265.html

Django中使用ajax技術概述

ajax 1.什么是ajax ajax就是在不刷新整個頁面的情況下&#xff0c;去更新局部頁面的內容&#xff08;無刷新技術&#xff09; 2.ajax有什么優點 最大的一點是頁面無刷新&#xff0c;在頁面內與服務器通信&#xff0c;給用戶的體驗非常好。 使用異步方式與服務器通信&#x…

IE、FF腳本兼容性問題

1.window.event IE有這個對象&#xff1b;FF沒有&#xff0c;FF通過參數傳遞 2.獲取事件源 IE&#xff1a;srcElement FF&#xff1a;target 3.添加與去除事件 IE&#xff1a;element.attachEvent("onclick", function(){}) element.detachEvent("onclick"…

ARM MOV和 LDR指令關系

ARM是RISC結構&#xff0c;數據從內存到CPU之間的移動只能通過L/S指令來完成&#xff0c;也就是ldr/str指令。比如想把數據從內存中某處讀取到寄存器中&#xff0c;只能使用ldr比如&#xff1a;ldr r0, 0x12345678就是把0x12345678這個地址中的值存放到r0中。而mov不能干這個活…