ITと雑記とド田舎と

ド田舎在住エンジニアがIT備忘録と雑記を書くブログです

HTML&CSS HTMLのタグと要素名 CSSの各部の呼び名まとめ

HTML&CSSの基本を勉強したので覚え書きです。

なんだろう、プログラミング言語だと覚えれるのにHTML&CSSだとすぐに忘れる。使う頻度の問題もあるでしょうし、大学時代に基礎からやってるプログラミングは覚えやすいというのもあると思いますが、なんとか知識を定着させたい。

 

HTML

「タグ」「属性」「コンテンツ」「終了タグ」

f:id:kdn-1017-wttd:20180730223549p:plain

 

CSS

セレクタ」「宣言ブロック」「プロパティ」「値」

f:id:kdn-1017-wttd:20180730223647p:plain

セレクタの種類

とりあえず基本用語さえ覚えておけばどうとでもなると思う(たぶん)。

 

Python Web開発フレームワークDjangoの「Django Girls Tutorial」をやってみました

久しぶりの更新です。

 

私は仕事でもプライベートでもweb開発をほとんど行ったことがないのですが、Webアプリは作れて損はないですよね。そんな中で今回はpythonのWeb開発フルスタックフレームワークDjango」の有名なチュートリアルDjango Girls Tutorial」の日本語版を試した感想記事になります。

 

感想

基本的にはチュートリアル通りに進めれば難しいところはありませんでした。ただ、前提としてpythonの基本とWebシステムの基本は知っていたほうがいいと思います。pythonを全く知らない人がDjangoに行きつくことはないと思いますが、Webに関しては以下の本がおすすめです。

「プロになるためのWeb技術入門」 ――なぜ、あなたはWebシステムを開発できないのか

「プロになるためのWeb技術入門」 ――なぜ、あなたはWebシステムを開発できないのか

 

 

Django Girls Tutorialをやれば、URLマッピング、ORM、テンプレートエンジンなどの基本を実際に動かすことができます。Herokuを利用したデプロイまでできるので、開発環境と本番環境の違いを意識することもできます。正直私が会社で新人の時に受けた教育よりもよっぽど丁寧です。とても良いチュートリアルだと思います。

少し気になったのは、日本語版のチュートリアルはDjango2.系に対応していません。英語版の本家のチュートリアルは対応されていました。Django2.系ではurl.pyのURLマッピングを行う関数がurl関数からpath関数に変更されています。私は英語版が対応していることに気づかず自力で調べてしまいました。最初から英語版を見ておけばよかった。英語が苦手という方は日本語版と並べながら作業を進めてみるといいかもしれません。

すべて終えて改めて思いましたが、フルスタックのWeb開発は覚えることが多くて大変ですね。私の場合大学時代はC言語で研究用のコードを書くことがメインで、社会人になってからWebに限らずアプリ開発を始めたのもあり、感覚に慣れるのに苦労しています。

本当は今回の記事も苦労したところであったり、具体的なコードを上げようかと思っていたのですが、あまりにチュートリアルが分かりやすかったので、本当にただの感想記事になってしまいました。そのくらい分かりやすいので興味のある方は是非試してみてください。

 

以前ブログ記事にも上げましたがTornadoは少し触ったことがあるので、次はFlaskを触ってみようと思っています。

python3 値渡しと参照渡し

python3 覚え書きNo.5

 

pythonの変数への代入はすべて参照渡しです。でも、値渡しをしたい時ってありますよね。私がC言語からプログラミングに入ったからでしょうか。

la = [[1, 2, 3], [4, 5, 6]]
lb = la
print(lb)

lb[0][0] = 777
print(la)

実行結果
[[1, 2, 3], [4, 5, 6]]
[[777, 2, 3], [4, 5, 6]]

 このようにリストlbにリストlaを代入した後、lbの値を変更するとlaの値も変更されます。laとlbがメモリの同一領域を参照しているからです。

 これを防ぐためにはモジュールcopyのdeepcopy関数を利用します。

from copy import deepcopy

la = [[1, 2, 3], [4, 5, 6]]

lb = deepcopy(la)
la[0][0] = 777

print(la)
print(lb)

実行結果
[[777, 2, 3], [4, 5, 6]]
[[1, 2, 3], [4, 5, 6]]

今度はリストlaの値を変更しても、lbの値が変更されていません。iteratorも値渡し出来ました。

 

numpy配列の値渡し

また、numpyを利用している場合、numpyのcopy関数を利用できます。

import numpy as np

npla = np.array([[1, 2, 3], [4, 5, 6]])
nplb = npla.copy()

npla[0, 0] = 777
print(npla)
print(nplb)

実行結果
[[777   2   3]
 [  4   5   6]]
[[1 2 3]
 [4 5 6]]

 値渡しが出来ていることが分かります。

 

 ただし以下の場合のように、numpy配列の中にリストが入っているような形式だとcopy関数を利用しても中のリストは参照渡しになるようです。

import numpy as np

npla = np.array([[1, 2, 3], [4, 5]])
nplb = npla.copy()

npla[0][0] = 777
print(npla)
print(nplb)

実行結果
[list([777, 2, 3]) list([4, 5])]
[list([777, 2, 3]) list([4, 5])]

python3 numpy配列と組み込みリストの相互変換

pytrhon3 覚え書きNo.4です。

 

ものすごく基本なんですが、ちょっとやらないとすぐ忘れるので自戒をこめて記録。

numpyの配列と組み込みのlistの相互変換です。

 

import numpy as np

l1 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(l1)
print('----------------------------------')
npl1 = np.array(l1)
print(npl1)
print('----------------------------------')
l2 = npl1.tolist()
print(l2)

実行結果
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
----------------------------------
[[1 2 3]
 [4 5 6]
 [7 8 9]]
----------------------------------
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

numpy.array(リスト)とnumpy配列.tolist()で終わり。シンプルですね。

ML Kit for Firebaseを利用してAndroidで文字認識

今回はGoogleのサービスFirebaseの機能の一つであるML Kitで文字認識を試してみたお話です。

FirebaseはMBaaSと呼ばれるサービスで、Mobile用のバックエンド機能をクラウドで提供するものです。AndroidiOSから利用できます。ML KitはGoogle I/O2018で発表された、Firebase上で機械学習のモデルを利用して画像認識などの機能を利用することができます。わたしは大学時代に機械学習を研究で少し利用していました(DNNが流行る直前くらいの時期ですが)。社会人になってからもニューラルネットワークフレームワークChainerを少し触ったこともあり、ML Kitも興味があったので試してみました。

 

ML Kit  for Firebaseの文字認識

Firebaseの準備

まずはML Kit fro Firebaseを利用する準備を行います。

f:id:kdn-1017-wttd:20180710064448p:plain

 

登録できたらFirebase consoleで新規プロジェクトを作成します。

f:id:kdn-1017-wttd:20180710065143p:plain

プロジェクト名には分かりやすい名前を付けておきましょう。

f:id:kdn-1017-wttd:20180710065332p:plain

プロジェクトを作成したらAndroidアプリにFirebaseを追加します。

f:id:kdn-1017-wttd:20180710065656p:plain

まず、Androidパッケージ名を決めます。Android Studioのプロジェクト作成時に設定するパッケージ名にも同じパッケージ名を利用します。次に、Android Studioのプロジェクトに読み込ませるjsonファイルをダウンロードして配置。最後にFirebase SDKを利用する設定をbuild.gradleに記述して準備完了です。Android Studioのプロジェクトを同時進行で準備しながら作業をすればよいと思います。

案内モーダルがとても分かりやすいのですが、1つ注意点があります。アプリレベルbuild.gradleの記述で'compile'となっている部分は、現在は'implementation'に変更されています。'compile'と記述するとgradleの同期で失敗するので気を付けましょう。

f:id:kdn-1017-wttd:20180710070232p:plain

f:id:kdn-1017-wttd:20180710070250p:plain

これでML Kitを利用する準備は完了です。

 

Androidで文字認識を動かす

ML Kitのそれぞれの機能にも公式のチュートリアルがあり、そちらがとても分かりやすく説明してくれています。文字認識についてもこちらを参考に行えば、Android開発の経験がある方ならそれほど迷わずに文字認識を実行できると思います。

Kotlinのチュートリアルもあったのですが、わたしはJavaでしか開発を行ったことがなかったので今回はJavaでコードを記述しました。

ML Kitはクラウドベースでサーバーに処理をお願いする方法とOn Deviceで行う方法があるようです。それぞれの特徴は

On Device

クラウド

  • 1000アクセス/月までは無料
  • 高精度
  • 多言語文字対応

今回はOn Deviceのみ試してみました。雑ですが、コードは以下のようになります。

package jp.koda.mlkit.ocrtest;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.ml.vision.FirebaseVision;
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
import com.google.firebase.ml.vision.text.FirebaseVisionText;
import com.google.firebase.ml.vision.text.FirebaseVisionTextDetector;

public class MainActivity extends AppCompatActivity {

    private final static int RESULT_CAMERA = 1;
    private ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = findViewById(R.id.imageView);

        Button takePictureButton = findViewById(R.id.take_picture_button);
        takePictureButton.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(intent, RESULT_CAMERA);
            }
        });

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        if(requestCode == RESULT_CAMERA) {
            Bitmap bitmap;

            if(intent == null) {
                return;
            }
            else {
                bitmap = (Bitmap) intent.getExtras().get("data");
            }
            imageView.setImageBitmap(bitmap);

            FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);

            FirebaseVisionTextDetector detector = FirebaseVision.getInstance().getVisionTextDetector();

            Task<FirebaseVisionText> result =
                    detector.detectInImage(image)
                            .addOnSuccessListener(new OnSuccessListener<FirebaseVisionText>() {
                                @Override
                                public void onSuccess(FirebaseVisionText firebaseVisionText) {
                                    for (FirebaseVisionText.Block block: firebaseVisionText.getBlocks()) {
                                        Rect boundingBox = block.getBoundingBox();
                                        Point[] cornerPoints = block.getCornerPoints();
                                        String text = block.getText();
                                        Log.i("OCR_RESULT", text);
                                        for (FirebaseVisionText.Line line: block.getLines()) {
                                            // ...
                                            for (FirebaseVisionText.Element element: line.getElements()) {
                                            }
                                        }
                                    }
                                }
                            })
                            .addOnFailureListener(
                                    new OnFailureListener() {
                                        @Override
                                        public void onFailure(@NonNull Exception e) {
                                            // Task failed with an exception
                                            // ...
                                        }
                                    });
        }
    }
}

 実機で文字認識させてみましたが、かなり精度よく出来ている印象でした。本当はBitmapを利用する方法ではなく、画像の回転情報もあつかえるByteBufferなどを利用する方法のほうがいいのかもしれません。

 

参考

MLKit for Firebase触ってみた(0) -概要/事前準備編- – 海鮮丼の国

アプリ開発が怖いほど楽になる「Firebase」を徹底解説!【初心者向け】

Python3 変数に関数を代入して呼び出し

Python3 覚え書きNo.3です。

 

変数に関数を代入すればいいという発想がなかなか思いつかなかったのでメモ。

多分デコレータのこととか考えると当然のことなんだろうな。精進します。

 

class MyClass:
    def __init__(self, select_num=0):
        if select_num == 0:
            self.call_func = self.my_func1
        elif select_num == 1:
            self.call_func = self.my_func2
        elif select_num == 2:
            self.call_func = self.my_func3
        else:
            self.call_func = self.my_func1

    def my_func1(self):
        print('Hello, func1!')

    def my_func2(self):
        print('Hello, func2!')

    def my_func3(self):
        print('Hello, func3!')

    def call_my_func(self):
        print('-------------------')
        self.call_func()
        print('-------------------')


test_func = MyClass(1)
test_func.call_my_func()

実行結果
-------------------
Hello, func2!
-------------------

 

pythonランチャーでバージョンを切り替える

 Python覚え書きNo.2です。

 

Windows10環境でPythonのバージョンを切り替える方法です。

Anacondaだったりで管理する方法もありますが、今回はPython3.3から標準で付属しているPythonランチャーを使います。

 

 

ファイルごとに切り替える

pyファイルの行頭で指定。

#!python3.5

コマンド実行時に切り替える

pyコマンドで実行するとインストールされている最新バージョンで実行される。

最新バージョンで実行しない場合、バージョンを指定する。

py -V
Python 3.7.0
py -3.5 -V
Python 3.5.2

 pipでライブラリインストール

pyコマンドでバージョンを指定してpipを利用する。

py -m pip install numpy
py -3.5 -m pip install numpy

 

 参考

Pythonの複数バージョンの扱い方(Windowsの場合) | ガンマソフト株式会社