L298Nを使ってモータの制御

L298Nとは


2つのモータを独立して駆動でき、正転逆転制御などに最適です。 制御は各モーターに対して、イネーブル(回転する/しない)と回転方向の指定を2線でおこないます。 マイコンでの制御のほか、スイッチなどによってマニュアル制御も簡単におこなえます。

L298N使用 2Aデュアルモーターコントローラー: マイコン関連 秋月電子通商 電子部品 ネット通販

http://akizukidenshi.com/catalog/g/gM-06680/   f:id:kobakenkken:20180515171831p:plain

Pin Description

  • ENA Motor A Speed Control

  • IN1 Motor A Direction Pin 1

  • IN2 Motor A Direction Pin 2

  • IN3 Motor B Direction Pin 1

  • IN4 Motor B Direction Pin 2

  • ENB Motor B Speed Control

Terminal Description

  • VMS 5-35V Input

  • GND 0V

  • 5V 5V input/output

  • OUT1 Motor A

  • OUT2 Motor A

  • OUT3 Motor B

  • OUT4 Motor B

RaspiとPythonによるモータ制御

import RPi.GPIO as gpio
import time
 
def init():
 gpio.setmode(gpio.BCM)
 gpio.setup(17, gpio.OUT)
 gpio.setup(22, gpio.OUT)
 gpio.setup(23, gpio.OUT)
 gpio.setup(24, gpio.OUT)
 
def forward(tf):
 init()
 gpio.output(17, True)
 gpio.output(22, False)
 gpio.output(23, True) 
 gpio.output(24, False)
 time.sleep(tf)
 gpio.cleanup()
 
def reverse(tf):
 init()
 gpio.output(17, False)
 gpio.output(22, True)
 gpio.output(23, False) 
 gpio.output(24, True)
 time.sleep(tf)
 gpio.cleanup()
 
print "forward"
forward(4)
print "backward"
reverse(2)
#!/usr/bin/python3.4
#MKerbachi November 6th, 2015
#Python code to control two motors with Rpi A+ with the H bridge l298n

import RPi.GPIO as GPIO # always needed with RPi.GPIO  
import time
import curses


# get the curses screen window
screen = curses.initscr()
 
# turn off input echoing
curses.noecho()
 
# respond to keys immediately (don't wait for enter)
curses.cbreak()
 
# map arrow keys to special values
screen.keypad(True)



#If the two GND (PI + l298n) are not interconnected that won't work !
#For all Keyboard symbols:
#https://docs.python.org/2/library/curses.html
  
GPIO.setmode(GPIO.BCM)  # choose BCM or BOARD numbering schemes. I use BCM  

#################################################################
#          Variables               #
#################################################################

#For Motor #1
GPIO.setup(18, GPIO.OUT)# set GPIO 01 as an output Enabler
GPIO.setup(24, GPIO.OUT)# set GPIO 05 as an output.
GPIO.setup(23, GPIO.OUT)# set GPIO 04 as an output.
  
p24 = GPIO.PWM(24, 100)
p23 = GPIO.PWM(23, 100)
p18 = GPIO.PWM(18, 100)    # create an object p for PWM on port 18 at 50 Hertz
                        # you can have more than one of these, but they need
                        # different names for each port
                        # e.g. p1, p2, motor, servo1 etc.

#For Motor #2
GPIO.setup(13, GPIO.OUT)# set GPIO 03 as an output Enabler
GPIO.setup(27, GPIO.OUT)# set GPIO 02 as an output.
GPIO.setup(17, GPIO.OUT)# set GPIO 0  as an output.

p27 = GPIO.PWM(27, 100)
p17 = GPIO.PWM(17, 100)
p13 = GPIO.PWM(13, 100)    # create an object p for PWM on port 18 at 50 Hertz  
                        # you can have more than one of these, but they need  
                        # different names for each port   
                        # e.g. p1, p2, motor, servo1 etc.  

LastKey = ""

#################################################################
#          Functions               #
#################################################################

def Stop():
            p18.start(0)
            p23.start(0)
            p24.start(0)

            p13.start(0)
            p27.start(0)
            p17.start(0)
            time.sleep(0.3)
            #GPIO.cleanup()
            print ("Stop executed")
            #exit()

def Left():
            if LastKey != 'left' : Stop()
            p18.start(60)
            p23.start(0)
            p24.start(100)

            time.sleep(0.4)
            p13.start(60)
            p27.start(0)
            p17.start(100)

#            time.sleep(0.3)
            #Stop()

def Right():
            if LastKey != 'right' : Stop()
            p18.start(60)
            p23.start(100)
            p24.start(0)

            time.sleep(0.4)
            p13.start(60)
            p27.start(100)
            p17.start(0)

#            time.sleep(0.3)
            #Stop()

def Up():
            #if LastKey != 'up' : Stop()
            p18.start(60)
            p23.start(100)
            p24.start(0)

            time.sleep(0.3)
            p13.start(60)
            p27.start(0)
            p17.start(100)

            time.sleep(0.3)
            #Stop()

def Down():
            #if LastKey != 'down' : Stop()
            p18.start(60)
            p23.start(0)
            p24.start(100)

            time.sleep(0.3)
            p13.start(60)
            p27.start(100)
            p17.start(0)

            time.sleep(0.3)
            #Stop()


try:
    while True:
        char = screen.getch()
        print ('you entred')
        print (char)
        if char == ord('q'):
            break
        #elif char == curses.KEY_ENTER:
        elif char == ord(' '):
            # print doesn't work with curses, use addstr instead
            #screen.addstr(0, 0, 'right')
            if not ( LastKey == "enter" ) : print ('Last key was not Enter, it was %s \n' % LastKey)
            LastKey="enter"
            print ('enter\n')
            Stop()

        elif char == curses.KEY_RIGHT:
            # print doesn't work with curses, use addstr instead
            #screen.addstr(0, 0, 'right')
            if not ( LastKey == "right" ) : print ('Last key was not right, it was %s \n' % LastKey)
            LastKey="right"
            print ('right\n')
            Right() 
           
        elif char == curses.KEY_LEFT:
            #screen.addstr(0, 0, 'left ')       
            if not ( LastKey == "left" ) : print ('Last key was not left, it was %s \n' % LastKey)
            LastKey="left"
            print ('left\n')
            Left()

        elif char == curses.KEY_UP:
            #screen.addstr(0, 0, 'up   ')       
            if not ( LastKey == "up" ) : print ('Last key was not up, it was %s \n' % LastKey)
            LastKey="up"
            print ('up\n')
            Up()

        elif char == curses.KEY_DOWN:
            #screen.addstr(0, 0, 'down ')
            if not ( LastKey == "down" ) : print ('Last key was not down t was %s \n' % LastKey)
            LastKey="down"
            print ('down\n')
            Down()
        else:
            print ('Nothing Entred!\n')

finally:
    # shut down cleanly 
    print ('In the finally section now')
    curses.nocbreak(); screen.keypad(0); curses.echo()
    curses.endwin()
    p13.stop()                # stop the PWM output
    p17.stop()
    p27.stop()

    p23.stop()                # stop the PWM output
    p24.stop()
    p18.stop()

    GPIO.cleanup()          # when your program exits, tidy up after yours




p13.stop()                # stop the PWM output  
p17.stop()
p27.stop()
  
p23.stop()                # stop the PWM output  
p24.stop()
p18.stop()

GPIO.cleanup()          # when your program exits, tidy up after yours

メモ

アナログ出力では周波数とデューティ比を指定して、モータ制御などに使うPWM制御ができます。

まずピンに対して周波数を設定してpwmオブジェクトを取得します。

pwm = GPIO.PWM([チャンネル], [周波数(Hz)]) 次にpwmオブジェクトに対してデューティ比を指定して出力を開始します。

pwm.start([デューティ比]) 例えば、ピン18に周波数1KHz、デューティ比50%でPWM出力する場合は以下のように書きます。

pwm = GPIO.PWM(18, 1000) pwm.start(50) 途中で周波数を変更する場合は以下の関数を使用します。

pwm.ChangeFrequency([周波数(Hz)]) 途中でデューティ比を変更する場合は以下の関数を使用します。

pwm.ChangeDutyCycle([デューティ比]) PWM出力を停止する場合は以下の関数を実行します。

pwm.stop() スクリプト終了時にはちゃんと停止しておきましょう。

request python まとめ

what is request

requestsとはサードパーティ製のhttp通信を行うためのライブラリ これを使用すると、webサイトのデータのダウンロードやrestapiの使用が可能 install cmd pip install requests

example

ヤフーのニュース一覧ページのhtmlを取得 import requests url = "https://news.yahoo.co.jp/topics" r = requests.get(url) print(r.text)

urlから画像ダウンロード

import urllib.error import urllib.request headers = { "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0", }

def download_image(url, dst_path, headers): try: # request = urllib.request.Request(url=url, headers=headers) # data = urllib.request.urlopen(request)

    data = urllib.request.urlopen(url,headers).read()
    with open(dst_path, mode="wb") as f:
        f.write(data)
except urllib.error.URLError as e:
    print(e)

url = 'URL' dst_path = 'lena_square.png'

dst_dir = 'data/src'

dst_path = os.path.join(dst_dir, os.path.basename(url))

download_image(url, dst_path, headers)

urlからhtmlコンテンツダウンロード

coding:utf-8

import urllib.request

url = "URL" headers = { "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0", }

request = urllib.request.Request(url=url, headers=headers) response = urllib.request.urlopen(request) html = response.read().decode('utf-8') print(html)

参考

http://www.python.ambitious-engineer.com/archives/974#requests

imgaugライブラリを使った機械学習用のdata augmentation

install

通常版

sudo pip install imgaug

最新版

pip install git+https://github.com/aleju/imgaug

必要なもの

  • six
  • numpy
  • scipy
  • scikit-image (pip install -U scikit-image)
  • OpenCV (i.e. cv2)

使い方

すべてのDA手法をお試しするならgenerate_example_images.pyを実行すればよし

DAの種類

kerasで実装できないものをまとめてみました。

ペッパー

f:id:kobakenkken:20180121160934j:plain

ガウシアンノイズ

f:id:kobakenkken:20180121155930j:plain

ソルト

f:id:kobakenkken:20180121155842j:plain

ペッパー

f:id:kobakenkken:20180121155820j:plain

ソルト&ペッパー

f:id:kobakenkken:20180121155803j:plain

piece wise affine(区分積分アフィン?)

f:id:kobakenkken:20180121155636j:plain

透視変換(perspective transform)

f:id:kobakenkken:20180121155611j:plain

crop(トリミング)

f:id:kobakenkken:20180121155536j:plain

平滑化フィルタ

median blur

f:id:kobakenkken:20180121154958j:plain

gaussian blur

f:id:kobakenkken:20180121155022j:plain

bilateral blur

f:id:kobakenkken:20180121155241j:plain

averageblur

f:id:kobakenkken:20180121155420j:plain

coarseシリーズ

coarse ソルト

f:id:kobakenkken:20180121160157j:plain

coarse ペッパー

f:id:kobakenkken:20180121160358j:plain

coarse Dropout

f:id:kobakenkken:20180121160414j:plain

coarse ソルト&ペッパー

f:id:kobakenkken:20180121160435j:plain

contrast normalization

f:id:kobakenkken:20180121160842j:plain

frequency noisealpha

f:id:kobakenkken:20180121160815j:plain

multiply (ピクセル演算)

f:id:kobakenkken:20180121160744j:plain

参考

https://towardsdatascience.com/image-augmentation-for-deep-learning-using-keras-and-histogram-equalization-9329f6ae5085

keras 学習済モデルの取り扱い全般まとめ

keras公式の学習済モデル読み込み方法

from keras.applications.inception_v3 import InceptionV3

InceptionV3 = InceptionV3(include_top=False, weights='imagenet', input_tensor=input_tensor)

kerasで利用可能なモデル

ImageNetで学習した重みをもつ画像分類のモデル:

  • Xception
  • VGG16
  • VGG19
  • ResNet50
  • InceptionV3
  • InceptionResNetV2
  • MobileNet
  • NASNet

参照 https://keras.io/ja/applications/

学習済モデルを利用した学習方法

  • 重み読み込み版(finetuning) weights='imagenet'を指定
from keras.applications.inception_v3 import InceptionV3

InceptionV3 = InceptionV3(include_top=False, weights='imagenet', input_tensor=input_tensor)
  • 重み読み込みなし版 weights='None'を指定
from keras.applications.inception_v3 import InceptionV3

InceptionV3 = InceptionV3(include_top=False, weights='None', input_tensor=input_tensor)
  • オリジナルの学習済モデルの場合(finetuning)
model.load_weights("./weight.19-0.70.hdf5", by_name=True)

model.load_weights(filepath, by_name=False): (save_weightsによって作られた) モデルの重みをHDF5形式のファイルから読み込む

デフォルトはモデルの構造は不変であることが前提

(いくつかのレイヤーが共通した)異なる構造に対して重みを読み込む場合,by_name=Trueを使うことで,同名のレイヤーにのみ読み込み可能

学習モデルの保存方法

model.save_weights(os.path.join('PATH', 'InceptionV3_scratch2.h5'))

ModelCheckpointを使った各エポック終了後にモデルの保存のしかた

keras.callbacks.ModelCheckpoint(filepath, monitor='val_loss', verbose=0, save_best_only=False, save_weights_only=False, mode='auto', period=1)

引数

  • filepath: モデルファイルを保存するパス.
  • monitor: 監視する値.
  • verbose: 冗長モード, 0 または 1.
  • save_best_only: save_best_only=Trueの場合,監視しているデータによって最新の最良モデルが上書きされない.
  • mode: {auto, min, max}の内の一つが選択されます.save_best_only=Trueならば,現在保存されているファイルを上書きするかは,監視されている値の最大化か最小化によって決定.

val_accの場合,この引数はmax

val_lossの場合はmin

autoモードでは,この傾向は自動的に監視されている値から推定します. * save_weights_only: Trueなら,モデルの重みが保存されます (model.save_weights(filepath)),そうでないなら,モデルの全体が保存されます (model.save(filepath)). * period: チェックポイント間の間隔(エポック数).

参考にしたもの

https://employment.en-japan.com/engineerhub/entry/2017/04/28/110000

ubuntu16.04でのTensorFlow環境構築でのメモ

TensorFlowのインストール

「libcupti-dev」を入れます。

sudo apt-get install libcupti-dev 「これはNVIDIA CUDAプロファイルツールインタフェースです。このライブラリは高度なプロファイリングのサポートを提供します。」だそうです。(TensorFlowより)

次にvirtualenvを入れます。これは入れといたほうがいいです(condaがあるならそれでいいですけど)。TensorFlowはバージョンアップするごとに仕様が少し変わるので、違うバージョンを試してみたいということは多々起こります。

一行目が2系用、二行目が3系用です。Pythonのバージョンに合わせて実行。

sudo apt-get install python-pip python-dev python-virtualenv sudo apt-get install python3-pip python3-dev python-virtualenv

インストール後は以下。こちらも一行目が2系、二行目が3系。

virtualenv --system-site-packages ~/tensorflow virtualenv --system-site-packages -p python3 ~/tensorflow

「~/tensorflow」のとこは別に自分の好きなディレクトリ名で結構ですが、まあ、これから変更する理由は特に無いと思います。

次に環境をアクティベートします。

source ~/tensorflow/bin/activate # bash, sh, ksh, or zsh source ~/tensorflow/bin/activate.csh # csh or tcsh

使っているターミナルに合わせて選んでください。ubuntuの入れたばかりならbashです。アクティベートされたらいよいよTensorFlowをインストール。

(tensorflow)$ pip install --upgrade tensorflow # for Python 2.7 (tensorflow)$ pip3 install --upgrade tensorflow # for Python 3.n (tensorflow)$ pip install --upgrade tensorflow-gpu # for Python 2.7 and GPU (tensorflow)$ pip3 install --upgrade tensorflow-gpu # for Python 3.n and GPU

TensorFlowが利用できるか確認 TensorFlowを利用するときはアクティベートが必要です。

以下のコマンドでできます。

source ~/tensorflow/bin/activate # bash, sh, ksh, or zsh source ~/tensorflow/bin/activate.csh # csh or tcsh

逆に終了する場合は

deactivate

参考にしたもの

s0sem0y.hatenablog.com

data augementation : mixup

mixup1は、2つの訓練サンプルのペアを混合して新たな訓練サンプルを作成するdata augmentation手法の1つ
具体的には、データとラベルのペア(X_1,y_1)(X_1,y_1), (X_2,y_2)(X_2,y_2)から、下記の式により新たな訓練サンプル(X,y)を作成します。ここでラベルy_1,y_2はone-hot表現のベクトルになっているものとします。X_1,X_2は任意のベクトルやテンソルです。
X=λX_1+(1−λ)X_2
y=λy_1+(1−λ)y_2
ここでλ∈[0,1]は、ベータ分布Be(α,α)からのサンプリングにより取得し、αはハイパーパラメータとなります。特徴的なのは、データX_1,X_2だけではなく、ラベルy_1,y_2も混合してしまう点です。
この定式化の解釈の参考記事:
http://www.inference.vc/mixup-data-dependent-data-augmentation/
実装

ジェネレータとして実装します。
https://github.com/yu4u/mixup-generator
import numpy as np

class MixupGenerator():
    def __init__(self, X_train, y_train, batch_size=32, alpha=0.2, shuffle=True, datagen=None):
        self.X_train = X_train
        self.y_train = y_train
        self.batch_size = batch_size
        self.alpha = alpha
        self.shuffle = shuffle
        self.sample_num = len(X_train)
        self.datagen = datagen

    def __call__(self):
        while True:
            indexes = self.__get_exploration_order()
            itr_num = int(len(indexes) // (self.batch_size * 2))

            for i in range(itr_num):
                batch_ids = indexes[i * self.batch_size * 2:(i + 1) * self.batch_size * 2]
                X, y = self.__data_generation(batch_ids)

                yield X, y

    def __get_exploration_order(self):
        indexes = np.arange(self.sample_num)

        if self.shuffle:
            np.random.shuffle(indexes)

        return indexes

    def __data_generation(self, batch_ids):
        _, h, w, c = self.X_train.shape
        _, class_num = self.y_train.shape
        X1 = self.X_train[batch_ids[:self.batch_size]]
        X2 = self.X_train[batch_ids[self.batch_size:]]
        y1 = self.y_train[batch_ids[:self.batch_size]]
        y2 = self.y_train[batch_ids[self.batch_size:]]
        l = np.random.beta(self.alpha, self.alpha, self.batch_size)
        X_l = l.reshape(self.batch_size, 1, 1, 1)
        y_l = l.reshape(self.batch_size, 1)

        X = X1 * X_l + X2 * (1 - X_l)
        y = y1 * y_l + y2 * (1 - y_l)

        if self.datagen:
            for i in range(self.batch_size):
                X[i] = self.datagen.random_transform(X[i])

        return X, y

training_generator = MixoutGenerator(x_train, y_train)()で、訓練データとラベルの集合を引数としてジェネレータを取得し、x, y = next(training_generator)で学習用のバッチが取得できます。
CIFAR-10データセットを利用してmixupした例です。


参考
新たなdata augmentation手法mixupを試してみた - Qiita