OmniAICreator/Qiita-1.07M huggingface dataset:
自分用 URL 短縮サービスを GSS で用意する

# なんで作ったの

Discord や Slack は投稿できる文字数に2000字の制限がある。URL にパラメータを持たせたりしている場合に URL の長さがしばしば2000字を越えてうまくチャットに投げ込めないことがあった。それへの対処として URL 短縮サービスを自前で用意してみよう、と考えた。

GAS を使ったことなかったし使ってみようと考えたのもある。
なお、既存の URL 短縮サービスでも API から登録できるものはあるので状況が許せばそちらを使えば良い。

# ソースコード

```javascript
function rndId(){
  var randomString = '';
  var baseString ='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  for(var i=0; i<8; i++) {
    randomString += baseString.charAt( Math.floor( Math.random() * baseString.length));
  }
  return randomString;
};

function doGet(e) {
  var output;
  if(! Boolean(e.parameters.id)) {
    output = HtmlService.createHtmlOutput('ID がないからうごかないよ');
    return output;
  }
  var id = e.parameters.id[0];
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('Sheet1');
  var sheetData = sheet.getRange('A1:B' + sheet.getLastRow()).getValues();
  var filteredData = sheetData.filter((data)=>{return data[0]===id});
  if(filteredData.length) {
    output = HtmlService.createHtmlOutput(`<a target="_blank" href="${filteredData[0][1]}">${id} のページ</a>`);
    return output;
  } else {
    output = HtmlService.createHtmlOutput(`ID ${id} がみつからないよ`);
    return output;
  }
}

function doPost(e) {
  var param = JSON.parse(e.postData.getDataAsString());
  var url = param.url;
  if(url) {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var sheet = ss.getSheetByName('Sheet1');
    var id = rndId();
    sheet.appendRow([id, url]);
    output = ContentService.createTextOutput("{\"result\":\"OK\", \"id\":\"" + id + "\"}");
  } else {
    output = ContentService.createTextOutput("{\"result\":\"parameter url is required\"}");
  }
  output.setMimeType(ContentService.MimeType.JSON);
  return output;
}
```

# 呼び出し方

## 登録 (post)

```bash
curl -L -H "Content-Type: application/json" -d "{\"url\":\"https://qiita.com/Chrysanthemum94\"}" "GASのURL"
```

GAS の URL は例えば `https://script.google.com/macros/s/IJbgPmbLuOWqWNLJTZHbgauirbunGDdmVcXnoDahtWBryKXEEPQlqsH/exec` 等。

## 取得 (get)

ブラウザでアクセスさせる。URL の末尾に `?id=ID` を付ける。
ID の値は post した際に得られる値を使う。例えば `https://script.google.com/macros/s/IJbgPmbLuOWqWNLJTZHbgauirbunGDdmVcXnoDahtWBryKXEEPQlqsH/exec?id=BbB7CZcJ`。

# 書いていて躓いたところ

## GAS に記載した内容が実環境に反映されない

保存する際に `Project version` を new にしないと更新されないので、注意が必要

## CURL で POST すると 302 Moved Temporarily が返ってくる

curl のオプションに -L を付けると転送してくれる

## GAS から HTML ってどうやって返すの

`HtmlService` を利用すると良い（ [公式のガイド](https://developers.google.com/apps-script/reference/html/html-service) ）
ファイルを置かずとも HTML を返すことは可能
Pythonにおける日付処理まとめ(datetimeとdateutil)

こんにちは、あんにんです。
DataCampで「Working with Dates and Times in Python」のコースを受講していたところ、あまりにも馴染みのない日付処理が多く（そもそもpd.to_datetimeくらいしか使ったことなかった私…）、「これはコース終わったらすぐ忘れる！やばい！」と思ったので、備忘録代わりにまとめておきたいと思います。

#datetime モジュール
日付や時刻を操作するためのモジュール
・Awareクラス：夏時間やタイムゾーンなどの時間調整に関する情報があるデータ
・Naiveクラス：ないデータ

＜基本＞
<b>datetime.datetime(datetimeオブジェクト)</b>・・・年月日時分秒（dateオブジェクトとtimeオブジェクトの情報を持っている一つのオブジェクト）

```
from datetime import datetime
today = datetime(2020, 6, 1, 15, 30, 00)
print(today)

Output: 2020-06-01 15:30:00 
```

datetimeはPOSIXタイムスタンプの値を変換したいとき（datetime.fromtimestamp）にも使える。


<b>datetime.date(dateオブジェクト)</b>・・・年月日のオブジェクト

```
from datetime import date
today = date(2020, 6, 1)
print(today)

Output: 2020-06-01
```
使えるメソッドはdatetimeと被っている（逆？dateオブジェクトで使えるものはdatetimeでも使える？？）.fromtimestampもそうだし、.isoformatとか。


<b>datetime.timedelta(timedeltaオブジェクト)</b>・・・経過時間や時間差など（Duration）

```
from datetime import date, timedelta
today = date(2020, 6, 1)
print(today + timedelta(days=7))

Output: 2020-06-08
```

timedelta()の引数には、days, hours, など色々。負の数でも機能する。


<b>datetime.astimezone(astimezoneオブジェクト)</b>・・・引数に指定されたタイムゾーンを適用する。

```
from datetime import datetime, timezone
today = datetime(2020, 6, 1, 15, 30, 00)
today = today.astimezone(timezone.utc)
print(today)

Output: 2020-06-01 06:30:00+00:00
```




#dateutil.tz モジュール
dateutilはdatetimeを拡張するパッケージです。
今回はDataCampで学習したタイムゾーン実装に強いtzモジュールのみ。


<b>tz.gettz()</b>・・・引数にあるタイムゾーンのインスタンスを作成。

```
from dateutil import tz
est = tz.gettz('America/New_York')
print(est)

Output: tzfile('/usr/share/zoneinfo/America/New_York')
```

単体で使用するといまいちピンとこないけど、大陸と都市名で各地域のタイムゾーンが引っ張ってこれるので、datetime系オブジェクトのtzinfoに入れて使える。

<b>tz.datetime_ambiguous()</b>…あいまいな時刻があるかどうか判断するオブジェクト。
「あいまいな時間(Ambiguous time)」とは、複数のUTCにマップされる時刻のこと。すごくわかりやすい例があったので、<a href="https://atsuoishimoto.hatenablog.com/entry/2016/12/26/135834">こちらのブログ</a>を一読のこと。

```
from dateutil import tz
from datetime import datetime

est = tz.gettz('America/New_York')
first_1am = datetime(2019, 11, 2, 1, 0, 0, tzinfo=est)
tz.datetime_ambiguous(first_1am)

Output: True //のはず。Pythonista3ではAttributeError出てしまった。
```

<b>tz.enfold()</b>・・・上記で出てきた曖昧な時間を区別するためのオブジェクト。
夏時間の時間を引数に入れると、夏時間終了後の時間で返してくれるらしい。
Documentを見てもいまいちわからなかったので、DataCampでの学習内容から推測。


#Pandas で日付型を扱うとき
pd.to_datetimeしか知らなかった私ですが、ほかにも色々ありました。

<b>pandas.DataFrame.tz_localize()</b>・・・naiveなDataFrameやSeriesを指定したタイムゾーンにローカライズする。

<b>pandas.DataFrame.tz_convert()</b>・・・awareなDataFrameやSeriesを指定したタイムゾーンにコンバートする。


#終わりに
あまり日付まわりを実装することがなかったので、初めて知ることが多かったです。
<a href="https://ja.wikipedia.org/wiki/Tz_database">tz database</a>というのも初めて知りました。
複雑だし、奥が深いのだな…と思いました。ほかの言語のことを知らないので、何とも言えないのですが、逆に言えばPythonでは色々なモジュールがあって、日付って触りやすいのでは？と思いました。

記述がまちがっている場合は、指摘してくださると助かります(*^^*)



# 参考ドキュメント
・https://dateutil.readthedocs.io/en/stable/tz.html
・https://docs.python.org/3/library/datetime.html
・https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.tz_localize.html
・https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.tz_convert.html
・
ラズパイ リレーモジュールの使い方 Python

#0.最初に
今回作るものがどういう感じで動くのか見てみたい方は、[こちら](https://youtu.be/QV2pnvX0O3I)(youtubeの動画)でどうぞ。

#1.ラズパイとリレーモジュールをつなげる
![Polish_20200601_154923646.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616944/1ac58f73-cdb8-1dc1-11f5-6c4eb2d2fa4c.jpeg)
さっそくこのリレーモジュールにワイヤーをつないでいきます。 
![IMG_20200601_154117.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616944/3b946ee1-dd3e-fecc-f189-13d82c546818.jpeg)
GND(緑)
IN1(青)
IN2(赤)
IN3(灰)
IN4(白)
VCC(黒)
![IMG_20200601_155921.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616944/5dbd0a88-d14e-2ea2-4f26-2a7a2b93c16c.jpeg)
GND(緑) >> Pin.6
IN1(青) >> Pin.11 GPIO 17
IN2(赤) >> Pin.7  GPIO 4
IN3(灰) >> Pin.5  GPIO 3
IN4(白) >> Pin.3  GPIO 2
VCC(黒) >> Pin.2 5V
![IMG_20200601_155936.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616944/10c489fa-c2af-1b39-bee7-f8e4780bc56f.jpeg)
#2.プログラムを書く
```relay.py
import RPi.GPIO as GPIO
import time

#GPIO.setwarnings(False)
#ピンが使われているみたいなエラーがでてきたらこれを追加するとうまくいきます。
GPIO.setmode(GPIO.BCM)
pinlist = [2,3,4,17]

for i in pinlist:
    GPIO.setup(i,GPIO.OUT)
    GPIO.output(i,GPIO.HIGH)

try:
    for i in pinlist:
        GPIO.output(i,GPIO.LOW)
        time.sleep(2)
    finally:
        print("End of Program!")
        GPIO.cleanup()
```
これを実行すると、リレーモジュールのランプが順番に点灯します。

#最後に
このリレーモジュールの使い方は[Youtube](https://www.youtube.com/watch?v=wDMue0R7aBg)でも解説しているのでそちらも良かったらご覧ください。質問等がございましたらその動画のコメント欄もしくは、この記事のコメント欄でどうぞ。また、いいなと思ったら[チャンネル登録](https://www.youtube.com/channel/UCDYbu9aViDvkubFcwgbbKDA)お願いします。
AtCoderBeginnerContest169復習＆まとめ（前半）

# AtCoder ABC169
2020-05-31(日)に行われたAtCoderBeginnerContest169の問題をA問題から順に考察も踏まえてまとめたものとなります．
前半ではABCまでの問題を扱います．
問題は引用して記載していますが，詳しくはコンテストページの方で確認してください．
[コンテストページはこちら](https://atcoder.jp/contests/abc169)
[公式解説PDF](https://img.atcoder.jp/abc169/editorial.pdf)

## A問題　Multiplication 1
> 問題文
> $A×B$を求めてください。

入力を受け取り，掛け算したものを出力しました．

```python:abc169a.py
a, b = map(int, input().split())
print(a * b)
```

## B問題　Multiplication 2
> 問題文
> $N$個の整数$A_1,...,A_N$が与えられます。
> $A_1×...×A_N$を求めてください。
> ただし、結果が$10^{18}$を超える場合は、代わりに"-1"を出力してください。

Pythonで参加していましたが，苦戦しました．
入力の最後に0があったらまずいため，全部の値を掛け算し続けるプログラムを書いて，"TLE"になってました．
最初に0があるかどうか確かめられれば，Pythonであればそんなに苦戦しなくて済んだはずなのですが，予想以上に時間使ってしまったのと，ペナルティが重なってしまいました（反省）．
Pythonのint型上限ないから大丈夫だと楽観視していたが，どんどん計算コストが上がることに気づけてなかった．

```python:abc169b.py
n = int(input())
a_list = list(map(int, input().split()))
if 0 in a_list:
    print(0)
else:
    ans = 1
    flag = 1
    for i in range(0, n):
        ans *= int(a_list[i])
        if ans > 10 ** 18:
            flag = 0
            break
    if flag == 0:
        print(-1)
    else:
        print(ans)
```

ちなみにペナ4回も出しました．

## C問題　Multiplication 3
> 問題文
> $A×B$の小数点以下を切り捨て、結果を整数として出力してください。
> 制約
>　・$0 \leq A \leq 10^{15}$
>　・$0 \leq B < 10$
>　・$A$は整数
>　・$B$は小数第$2$位まで与えられる

小数の計算に誤差が発生することは知っていたので，100倍して整数にすれば，問題なく計算できると思って，入力$B$に対して100倍して計算する方法を提出したのですが"WA"になって絶望してました．
最初に提出した"WA"が返ってきたコード．

```python:abc169c.py
a, b = input().split()
a = int(a)
b = int(float(b) * 100)
print(a * b // 100)
```

何が原因かわからず，いろいろ試行錯誤したのですが，中々通らず，最後は入力$B$をfloatに変換せずに，文字列から三桁の整数として直接，数字列に変換することで"AC"通すことができました．
小数を100倍して整数にするところでも誤差が発生するとは知らなった（例題が問題なく解けたので，原因がまったくわからなかった）．

```python:abc169c.py
a, b = input().split()
a = int(a)
b = int(''.join(b.split(".")))
x = a * b
print(x // 100)
```

C問題も"AC"出すまでに4ペナでした．

前半はここまでとなります．
個人的に，苦手な部分の詰め合わせみたいな感じで，A問題のみで終わってrateガタ落ちするのではと焦ってしまったのも，解くのに時間がかかった原因かなと思っています．
本当にコンテスト中は理由がわからず絶望してました（ジャッジ結果も表示方法が告知なく変わっていて，どのくらいの問題が通せているのかすらわからなかったのも原因です）．
前半の最後まで読んでいただきありがとうございました．

後半はDEF問題の解説となります．
[後半に続く](https://qiita.com/takaito0423/items/71f5dc29522058d0a427)．
[UE4] テキスト読み上げ機能(アクセシビリティ)

対象Ver：UE4.25.0

#1. 概要
　加触性、近接性 (Accessibility)とはアクセスのしやすさ、近づきやすさのことであり、以下のサイトでも説明されています。

[Twenty-First Century Communications and Video Accessibility Act](https://www.fcc.gov/general/twenty-first-century-communications-and-video-accessibility-act-0)
[ビデオゲームとアクセシビリティにまつわる最近のトピックス](http://accessibility-tech.blogspot.com/2019/01/blog-post_21.html)

 要約すると、近年は障がいを持つ人もゲームをプレイできるよう、アクセシビリティ(ユーザーインタフェースや操作方法など)を提供する必要が要件として追加されています。UE4では4.23以降で[「NVDA」](https://www.nvda.jp/)などのテキスト読み取りソフトをサポートしており、視覚に障がいを持っている方でもプレイのサポートをするための機能が備わっています。

 以下の動画がこの機能で実現するイメージに近く、ゲーム内のテキストを音声読み上げすることが可能となります。
https://www.youtube.com/watch?v=4ygm9hcechg

#2. 機能
　公式ドキュメントがありますので、そちら参考にすると早いかと思います。
[スクリーンリーダーをサポートする](https://docs.unrealengine.com/ja/Engine/UMG/UserGuide/ScreenReader/index.html)

　この機能を要約して簡単に説明すると、以下のようにテキストにマウスカーソルを当てると、テキストの内容を読み上げてくれます。テキストの読み上げはNVDAのソフトが行うので、読み上げるテキストの内容をWidgetのDesignerから設定したり、カーソルを当てたら読み上げソフトに通知してくれる部分をEngineが自動で行います。この機能はドキュメントにもあるように、iOSとWindowsのみがサポートされています。
　例えば以下のようなテキストのUI表示があった場合、ユーザーはマウスカーソルでテキストに触れると文字を読み上げます。これは勿論ですが、音声読み上げソフトが起動している時のみ有効です。

![2020-06-01_15h23_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/f1e46724-8b4b-5eba-bc3a-a57884951bf4.png)

#3. 使い方
**・機能を有効にする**
「Accessibility.Enable=1」をConsoleVariable.iniで定義するかコンソールコマンドで実行します。
Windowsの場合はFWindowsApplication::ProcessMessageでウィンドウズメッセージの「WM_GETOBJECT」をトリガにFWindowsUIAManager::GetWindowProviderが実行されて読み上げを開始可能な状態となります。これはNVDAのアプリケーションを起動して有効にしておくことで、UE4側に通知されてくるためです。

**・読み上げテキストを設定する**
Widgetの以下の箇所から設定が可能です。各項目については[公式ドキュメント](https://docs.unrealengine.com/ja/Engine/UMG/UserGuide/ScreenReader/index.html)を参照してください。ゲーム側では読み上げテキストの内容を指定したりします。

![2020-06-01_15h29_15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/67902ff8-8eb8-3d22-fa3d-18fedefff1c2.png)
ホワイトハッカーとは

# はじめに
最近、セキュリティについて調べる機会が有り、ホワイトハッカーという単語に興味を持ったのでまとめてみました。

# ホワイトハッカーとは
（攻撃者として）ハッカーと同等のスキルを持ち、その知識と技術をセキュリティのために使う人間

## ホワイトハッカーのスキルが役立つ場面

- 防御  
防衛手段の立案、機器の構築・設定など
- 監視  
状況の確認、対策の評価など
- 検出  
異常の確認と特定など
- 分析  
インシデントの確認や根本原因の特定など
- 対応  
適切で効率的な対応とフィードバックなど

## 今後必要となるセキュリティ人材

- ホワイトハッカーのような高度なセキュリティ技術者
- 安全な情報システムを作るために必要なセキュリティ技術を身に着けた人材
- ユーザ企業において社内セキュリティ技術者と連携して、企業の情報セキュリティ確保を管理する

[経済産業省の資料](https://www.meti.go.jp/shingikai/sankoshin/shomu_ryutsu/joho_keizai/it_jinzai/pdf/002_03_00.pdf)

# ホワイトハッカーになるために必要な基本項目

- 知識
- 技術
- 倫理観

クライアントは攻撃なのかホワイトハッカーなのか区別がつかないので、`「クライアントの同意と強い倫理観」`が重要
攻撃側の後手に回らないように注意しなければならない。

# ハッカーとクラッカー

## ハッカーとは
優れたコンピュータスキルを持つ個人で、コンピュータのソフトウェアやハードウェアを作成して、調査することができる人物

## クラッカーとは
ハッキングの技術を犯罪等に利用する人

## 攻撃が生まれる方程式
攻撃 = 方法 + 脆弱性 + 動機

### 動機とは
・宗教的・国家的・民族的な利害関係
・怨恨
・金銭
・享楽

## 攻撃特定性

・ターゲットを選別する理由
多くは動機に依存する。

攻撃特定性が高い場合は、`「そのターゲットを攻撃するしか意味がない」`
攻撃特定性が低い場合は、`「攻撃できればどこでもいい」`

# ハッカーの種類

- ブラッグハット
- ホワイトハット
- グレーハット  
グレーハットは再犯性の高い人間
- サイバーテロリスト
- ハクティビスト  
(宣伝を目的とする)
- 国営ハッカー
- スーサイドハッカー  
(捕まってもいいと思っているハッカー)
- スクリプトキディ  
(スキルの低い人間→仕入れた技術をただ使うだけ)

# まとめ
セキュリティやネットワークについての技術・知識は今後、必須だと思うので、クラウドの学習と並行して学んでいきたいと思います。
Android関連 利用頻度高い製品のバージョン (2020-06-01)

# 2020-06-01 現在 Android関連 利用頻度高い製品のバージョン

個人的に特定時期のバージョン情報がまとまっていると嬉しいのでまとめたものです。

## Android Studio

4.0.0 (2020-05-28)

Download Android Studio and SDK tools  |  Android Developers
https://developer.android.com/studio

Android Studio release notes  |  Android Developers
https://developer.android.com/studio/releases

## Gradle

6.4.1 (2020-05-15)

Gradle Build Tool
https://gradle.org/

Gradle | Releases
https://gradle.org/releases/

## Android Gradle plugin

4.0.0 (April 2020)


Android Gradle plugin release notes  |  Android Developers
https://developer.android.com/studio/releases/gradle-plugin?hl=en




## Kotlin

Kotlin 1.3.70 (2020-03-03)

Kotlin Programming Language
https://kotlinlang.org/

Kotlin 1.3.70 Released | Kotlin Blog
https://blog.jetbrains.com/kotlin/2020/03/kotlin-1-3-70-released/

Kotlin コルーチンでアプリのパフォーマンスを改善する  |  Android デベロッパー  |  Android Developers
https://developer.android.com/kotlin/coroutines?hl=ja



## RxKotlin

RxKotlin 3.0.0 (2020-03-21)

ReactiveX/RxKotlin: RxJava bindings for Kotlin
https://github.com/ReactiveX/RxKotlin

Releases · ReactiveX/RxKotlin
https://github.com/ReactiveX/RxKotlin/releases


## OkHttp

Version 4.7.2 (2020-05-20)

square/okhttp: Square’s meticulous HTTP client for Java and Kotlin.
https://github.com/square/okhttp/releases


okhttp/CHANGELOG.md at master · square/okhttp
https://github.com/square/okhttp/blob/master/CHANGELOG.md


## Retrofit

Version 2.9.0 (2020-05-20)

Retrofit
https://square.github.io/retrofit/

retrofit/CHANGELOG.md at master · square/retrofit
https://github.com/square/retrofit/blob/master/CHANGELOG.md


## Moshi

Version 1.9.2 (2019-11-17)

square/moshi: A modern JSON library for Kotlin and Java.
https://github.com/square/moshi

moshi/CHANGELOG.md at master · square/moshi
https://github.com/square/moshi/blob/master/CHANGELOG.md



## Realm

7.0.0(2020-05-16)

Realm: Create reactive mobile apps in a fraction of the time
https://realm.io/

realm-java/CHANGELOG.md at master · realm/realm-java
https://github.com/realm/realm-java/blob/master/CHANGELOG.md

## Timber

Version 4.7.1 (2018-06-28)

JakeWharton/timber: A logger with a small, extensible API which provides utility on top of Android's normal Log class.
https://github.com/JakeWharton/timber

timber/CHANGELOG.md at master · JakeWharton/timber
https://github.com/JakeWharton/timber/blob/master/CHANGELOG.md
Mac(macOS Mojave)でnginxが起動しなくなったけど直ったメモ

## エラー内容

```bash
❯ sudo nginx                                                                                                                                                                                                                           ✘ 134 
dyld: Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib
  Referenced from: /usr/local/bin/nginx
  Reason: image not found
[1]    15059 abort      sudo nginx
```


```bash
❯ sudo nginx                                                                                                                                                                                                                           ✘ 134 
dyld: Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib
  Referenced from: /usr/local/bin/nginx
  Reason: image not found
[1]    15059 abort      sudo nginx
```


## やったこと


```bash
brew switch openssl 1.0.2s
```
なぜ動くようになるかはわからない
nginxが新しいバージョン(?)のopensslに対応していないのかもしれない

https://stackoverflow.com/questions/59006602/dyld-library-not-loaded-usr-local-opt-openssl-lib-libssl-1-0-0-dylib
Zeppelin 0.9.0-preview1 + Spark でCPUとメモリの使用量の設定

# 環境

* Apache Zeppelin 0.9.0-preview1
* macOS 10.15
* Docker(docker-compose)
* Spark 2.4.4
* Scala 

# 留意点

* 試した環境が、preview1 ということなので、変更されるかもしれません。

# 概要

* 単体のSparkで、最大のCPU、メモリを使うことができていたので、Zeppelin on Docker 環境でも実現したいと思いました。
* 直感で Zeppelin - interpreter - Spark の項目を設定してみたのですが、反映されないように感じました。
* 公式サイトとコードを読みながら、試行錯誤して目的を達成しました（正確性の保証はございません）。

# 私が試して成功した方法

## CPUの使用コア数の設定方法

### 方法1「Zeppelinの設定画面を利用する」

* dockerが利用するCPUコア数を設定します。
* http://localhost:8080/#/interpreter から設定する
* Interpreters - Spark - propaties に spark.master=local[*] を新規に追加
* Interpreters - Spark - propaties に spark.cores.max=16 を新規に追加(なくても良さそうです)

![ss1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198185/03871add-ca70-08a1-8795-20423c6f6dd5.png)


### 方法2「環境変数を設定する」

* dockerが利用するCPUコア数を設定します。
* 環境変数 ZEPPELIN_INTP_JAVA_OPTS に'-Dspark.master=local[*]'を設定します。アスタリスクはコア数の指定で、アスタリスクにすると最大値になります。
* 環境変数は、/zeppelin/conf/zeppelin-env.sh で設定できるようです（他の設定項目が列挙されているので、読むと勉強になります）。
* 以下の例は、docker-compose.yml です。
 
```
environment:
  ZEPPELIN_INTP_JAVA_OPTS: '-Dspark.cores.max=16 -Dspark.master=local[*]' 
```

## メモリの設定

* dockerが利用するメモリ量を設定します。
* Zeppelin - Interpreter - Spark でメモリ関連の設定をします。
* 環境変数 ZEPPELIN_INTP_MEM で JVM が使用するメモリについて設定します。
* 以下に docker-compose.yml の設定例を示します。
* 環境変数の設定は、/zeppelin/conf/zeppelin-env.sh でもできるようです。

```
environment:
  ZEPPELIN_INTP_MEM: '-Xms2g -Xmx16g'
```

### JVM メモリ利用量の設定

オプション|意味
---|---
-Xms|起動時に確保するメモリ
-Xmx|メモリの最大値

> The flag Xmx specifies the maximum memory allocation pool for a Java virtual machine (JVM), while Xms specifies the initial memory allocation pool.

* https://stackoverflow.com/questions/14763079/what-are-the-xms-and-xmx-parameters-when-starting-jvm

# Executorsの確認(CPUとメモリの割り当ての確認)

* http://localhost:4040/executors/ を開く

![ss2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198185/c269a169-b302-0472-d900-c8346593821f.png)



# Spark Contextの設定値の確認

### 方法１「設定値の確認方法」

* http://localhost:4040/environment/ を開く

### 方法2「API呼び出し」

```
// 全ての設定
spark.sparkContext.getConf.getAll.foreach(println)

// spark.masterの設定
println(spark.sparkContext.getConf.get("spark.master"))
```
JupyterNotebook 設定～使用方法(EC2 Amazon Linux2)

#JupyterNotebook使用方法

サーバで実行するなどの画面がない状態でwebから開きたいときの起動方法。
今回はEC2(amazonlinux2)で実行

```
#パスワードの設定(パスワード付けないなら飛ばす)
$ ipython
In [1]: from notebook.auth import passwd
In [2]: passwd()
Enter password:
Verify password: 
Out[3]: 'sha1:...' # 暗号化された文字列をコピーしておく
	
#rootユーザーでログイン
$ sudo su - 
$ mkdir /root/.jupyter
$ cd /root/.jupyter
$ openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mykey.key-out mycert.pem
	
#jupyternotebook初期設定
$ vi /root/.jupyter/jupyter_notebook_config.py
c = get_config()
c.NotebookApp.ip='0.0.0.0' # 任意のipアドレスからアクセス可
c.NotebookApp.password = u'sha1:...' # コピーしておいた文字列(パスワード付けないなら書かない)
c.NotebookApp.open_browser=False # jupyter起動時にブラウザを自動で開かない
c.NotebookApp.port=8888 # サーバーのport 今回は8888
c.NotebookApp.certfile = u'/root/.jupyter/mycert.pem' # サーバ証明書
c.NotebookApp.keyfile  = u'/root/.jupyter/mykey.key' # 秘密鍵
c.NotebookApp.notebook_dir = '/root/work' # 任意のフォルダ
	
#jupyter notebookを開く
$ jupyter notebook --ip='0.0.0.0' --allow-root &

#起動したら「http~~~/~~token=xxxxxxxxxxx」が標準出力に出てくると思うので、xxxxxxxxxx部分をコピーする
```

IEを立ち上げてurl欄にIP、ポートを打ち込むと立ち上がる。

```
http://xxx.xxx.xxx.xxx(EC2のグローバルIP):yyyy/
 xxx.xxx.xxx.xxx：EC2のグローバルIP
 yyyy：jupyter_notebook_config.pyに設定したポート(デフォルトは8888かな？)
```
MQL5-swich と case文の使い方 8

#はじめに
この記事は以下リンクのYoutubeビデオを翻訳したものになります。よければそちらもご覧ください。

https://www.youtube.com/watch?v=o2mN-ZwaUsQ&list=PLV8YK-9p3TcOmgAFIjntw-GxOJoHp9xwc&index=8

前回記事 は以下です。

https://qiita.com/James_KW/items/c99dd545389ef2004713

#ifを並べるのは...
プログラミングしていると、しばしば、「もし、○○だったらAをする、ちがってたら何もしない」という2択ではなく、「◎だったらA、△だったらB、×だったらC、◇だったらD・・・」のように4択や5択になることもある。一個一個すべてifで確認して条件分岐していってもいいのだがswich文など便利なものもある。

#実例
```c

int choice = 1;


void OnTick()
  {
   string entry = "";

   switch(choice)
     {
      case 1:
         entry = "RSIがほしい";
         break;

      case 2:
         entry = "ボリンジャーバンドがほしい";
         break;

      case 3:
         entry = "単純移動平均線がほしい";
         break;

      case 4:
         entry = "MACDがほしい";
         break;

      case 5:
         entry = "ZigZagがほしい";
         break;

      default:
         entry = "何もいらない";
     }
     Comment(entry);
  }
```

さて、これをこのままコンパイルして動かすと”RSIがほしい”というふうにCommentででてくるはずである。
一行目の

```cpp
int choice = 1;
```

ここで後に続くswich文のどの場合に移行するのかを決めている。ここでは1の場合ということである。

そして問題のswich文本体は以下のとおりである。

```cpp
   switch(choice)
     {
      case 1:
         entry = "RSIがほしい";
         break;

      case 2:
         entry = "ボリンジャーバンドがほしい";
         break;

...以下省略
```

switch()のかっこの中にint型の数値を与えて、なかのcaseの番号に当てはまっている処理に回るのである、
今回はwitchに入力されている数値は1なので、 case 1: の部分が動くのである。一度これを動かしてみたら、一行目のchoice変数の中身を変更してみてもう一度やってみよう。
Site24x7のZoom監視を使ってみた

こんにちは。@Miu24x7です。

みなさんZoom使ってますか？コロナで自宅にいる時間が増えた影響で利用し始めた方も多いと思います。
そんな今話題のZoomのパフォーマンスをSite24x7で監視できるようになりました！

私も早速試してみたので、今回はその設定方法を紹介します。

#Site24x7とは
Site24x7はWebサイト、サーバー、AWSなどのクラウド等を監視できるオールインワン型クラウドサービスです。
Zoomだけでなく、最近Nutanixも監視できるようにもなっています。クラスタ、ホスト、VM単位で監視が可能です。これ以外にも日々新しい機能が追加されてます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/83b68f46-9090-375c-3f5f-bb667bc1ec4d.png)

##Site24x7側の設定
それではまずSite24x7上で連携設定を行っていきます。

1. Site24x7にログイン
2. [管理] → [アプリケーションログ] → [ログの種類]の順にクリック
3. 画面右上の[ログの種類を追加]をクリック
4. "表示名"を任意に入力（Zoomイベントなど）
5. "ログの種類"に"zoomevents"と入力
6. それ以降の項目が自動的に入力される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/f93f9692-56c9-5c86-963a-12693f17efa4.png)
7. 同ページ下部にある"APIアップロード"を有効化
8. 表示された次の形式のURLをコピー（Zoom側の設定で使います）
https://logc.site24x7.com/event/receiver?token=....

9. [保存]をクリック

##Zoom側の設定
1. [Zoomマーケットプレイス](https://marketplace.zoom.us/)にアクセスしてログイン
2. 右上の[Develop] → [Build App]の順にクリック
3. Only Webhook欄の[Create]をクリック
4. アプリ名を入力し、[Create]をクリック
5. 次の情報を入力して[Continue]をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/679ffbe0-ff8a-3afd-4c44-4a4630ed2ffc.png)
6. Event Subscriptionsのトグルボタンを有効にし、[Add new event subscription]をクリック
7. 表示されたドロップダウンに次の情報を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/39f50861-81e4-bd21-72e4-abcc9353d8de.png)
（**Subscription Name**は任意、**Event notification…**はSite24x7画面の"APIアップロード欄"で取得したもの）
8. [Add event]よりをクリックしてどのアクションデータをSite24x7に送るか選択
9. [Save]をクリック後、[Continue]をクリック
10. 次の画面になれば完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/2d2a90d7-e34f-8b55-ffb0-7ec2ecb7c152.png)

#連携結果
連携後、Zoomでミーティングを開始した後、Site24x7上でログを吐き出してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/896ed709-4131-6a3e-917d-f85c2edaac1e.png)
無事にログが出力されてますね！

画面の"ダッシュボード"をクリックすると、ダッシュボード形式で表示もできるみたいです…！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514960/4f30243a-8e1c-e68a-764f-405a5201e924.png)
（[Site24x7ユーザーガイド](https://www.site24x7.jp/help/log-management/zoom-monitoring.html)より引用）

#最後に
今回はSite24x7にZoomのログを出力して、メトリクス管理をしやすくしてみました。
在宅勤務や遠隔教育、テレビ会議等が重視されてきた昨今にはとても嬉しい機能です！

Site24x7では無料期間を設けていますので、ご興味があればぜひお試しください！
https://www.site24x7.com/signup.html
MySQLでテーブル上のデータの消去

#使い方
データを消去するには**DELETE**文を使います。

```sql
DELETE FROM table_name [WHERE where_condition]
```

##例
テーブル名`talbe`からidカラムが10のデータを消去する。

```sql
DELETE FROM table WHERE id=10;
```

テーブルからすべてのデータを消去する。

```sql
DELETE FROM table;
```
Docker(19.03)でgpu使って学習したかった時の覚書ーTensorflow/Keras

#はじめに
DockerインストールしなおしてみたらDocker環境下TFやKerasで学習しようとしたときにGPU認識してくれなくてしばらくハマったので覚書です。

#こういう環境にしたい

Docker　19.03

--コンテナ内--
ubuntu 18.04
cuda 10.0
cudnn 7.4
tensorflow-gpu 1.14.0
keras : latest

[過去記事](https://qiita.com/kiii142/items/eadfaf5cf305981353e8)のResNet学習環境を作ることとします。

#気を付けることその0：Dockerのバージョン
まずここが違ってくるとお話になりません。
旧と現では結構コマンドも変わってきてる模様。
確認して合う環境を構築しましょう

docker環境確認方法はホスト側で以下コマンドです

```
docker version
```

今回はDockerバージョン19.03を対象とします


#気を付けることその1：コンテナ立ち上げ時のコマンド
いつのまにか`--runtime=nvidia`じゃなくなってたので注意
GPU使いたいときは`--gpu all(もしくは番号指定)`コマンドになったんだそうで
より直感的ですね。
こちらの記事を参考
[https://qiita.com/ksasaki/items/b20a785e1a0f610efa08](https://qiita.com/ksasaki/items/b20a785e1a0f610efa08)

#気を付けることその2：cuda,cudnn,tensorflow-gpu,pythonのバージョン
毎回引っかかるんだけどここに齟齬あるとほんと動きません。
オフィシャルの動作確認表を参考に入れましょう
LinuxのGPU周りの整合表は以下の通りでした。macは別表へ
[https://www.tensorflow.org/install/source#gpu](https://www.tensorflow.org/install/source#gpu)

今回はtensorflow-gpu==1.14.0が使いたかったので、それに合わせてCUDA10.0,cudnn7.4,python3.6を入れることとします。

#環境構築していく
今回はcuda,cudnnのバージョンを狙い打ちたいので下記のコマンドでコンテナ立ち上げました

```
docker run --gpus all -it (ここにいろいろコマンド)--name test_container nvidia/cuda:10.0-cudnn7-devel-ubuntu18.04 /bin/bash
```

実際は(ここにいろいろコマンド)部分に細々としたディスプレイ設定とかディレクトリのマウント設定とか付け足してます
[過去記事参照](https://qiita.com/kiii142/items/1946c3b9f0e15d56e817)ください

あらかじめdockerfileとかに書けたらいいんだろうけどそれもそれで面倒なので必要なものを後からいれていきます。

```
apt update
apt install python-pip3 
pip3 install tensorflow-gpu==1.14.0 keras matplotlib scikit-learn pillow
```

これで学習まわるはず

#GPU使えてるか？の確認
学習回し始めた時にワーニング文的なのが出るのでそこ確認しても良いし
一度```Ctrl + P + Q```でコンテナから抜けて
コマンド

```
nvidia-smi
```
でGPUの占有率見ることでも確認できます。

#おわりに
Dockerまわりもう少しお勉強が必要そう
より良いコマンドを探していきたいです
Visual Studio 2019 のデバッガーでメソッドの戻り値見たいんですが

やってしまった。

以下のようなツイートをしたのですが

```
そういえば Visual Studio でデバッグしてて、メソッドの最後の閉じ括弧にいるときは 
$returnvalue をウォッチ式として入れると戻り値が見れるという豆知識
```

まゆき先生に指摘されたのですが間違ってました orz

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">$returnvalue は最後にステップオーバーなどで実行したメソッドの戻り値が入っている、なのでメソッドの最後にブレークポイントを置いても見れないですね。かずきさんの例のだと ToArray の結果(暗黙変換でActionResultになったやつ)が見えているという感じ。<a href="https://t.co/OqahtaUNY2">https://t.co/OqahtaUNY2</a> <a href="https://t.co/DeJ5kEmOx7">pic.twitter.com/DeJ5kEmOx7</a></p>&mdash; Mayuki Sawatari (@mayuki) <a href="https://twitter.com/mayuki/status/1267341031139229696?ref_src=twsrc%5Etfw">June 1, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

$returnvalue はステップオーバーなどで実行したメソッドの戻り値が入ってるということなので、私の閉じ括弧の位置では、まだ戻り値は入っていませんでした。

私のコードだと、ToArray して暗黙の型変換されたものを return してたので return の結果と一致してただけでした。残念 orz

ということで、じゃぁメソッドの戻り値見たい場合は、どうすればいいの？ということですが、軽く見た感じ上記ツイートの位置にブレークポイントがある時点では無理っぽいです。

return 文に書いてある式に**副作用が無いケース**では以下のように return から先を選択して Shift + F9 のクイック ウォッチで確認することも出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/85351648-163b-0985-994a-248245ec7fec.png)

副作用がある場合はおとなしくステップオーバーをしてメソッドから抜けます。
メソッドから抜けると、メソッドの戻り値を変数に入れていない場合でも自動変数に結果が表示されます。自動変数を見たい場合はデバッグ中にメニューの「デバッグ」→「ウィンドウ」→「自動変数」で表示されるウィンドウで見れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/7ad5e7e9-b528-0786-2257-8edd80ce2003.png)
GIPによるアクセス制限はそろそろやめないか

#はじめに
掲題の通りです。
そろそろGIP(Global IP Address)によるアクセス制限はやめませんか？

#GIPによるアクセス制限の定義
ここで伝えたいGIPによるアクセス制限とは以下です。

* アクセス元IPアドレスを使用したサービスへのアクセス許可/拒否の制御

SaaSなどのインターネットに開かれているシステムに対して、クライアントのアクセス元GIPによる制御をやめたほうが良いと考えています。
以降、理由について述べます。

#SaaSが当たり前に
政府がクラウド・バイ・デフォルト原則をうたっているように、もうクラウドが当たり前です。
参考: https://pfs.nifcloud.com/navi/beginner/cloud_by_default.htm

SaaS同士を連携しようとした際に、「信頼できるGIP」をSaaS上で登録したりします。
この方式はSaaSが大規模になればなるほど、登録すべきGIPの範囲が拡大します。
SaaSの進退に応じて柔軟に変更できる運用を敷けるのであれば止めはしませんが、そんなことに労力を割くべきではないと考えます。
なにより、SaaSの良さ殺してますよ。

#SD-WANの台頭
様々なベンダー様がSD-WANの提供を行っており、多くの可能性を秘めていると感じます。

* Palo Alto Networks社 - [Prisma Access](https://www.paloaltonetworks.jp/cloud-security/prisma-access)
* Cato Networks社 - [Cato Cloud](https://www.catonetworks.com/jp/cato-cloud/)

これらのサービスは、クライアントをインターネット上の仮想ネットワーク上へ接続させ、仮想ネットワーク上から、インターネットへアクセスさせるという概念の製品群です。
この概念は、以下のような既存ネットワークインフラの問題を解決する銀の弾丸になりえます。

* ネットワーク利用状況が見えない
* 回線品質を向上できない
* アクセス増による回線コストの増大
* ローカルブレークアウトが出来ない
* プロキシサーバーの維持・更改が限界

今後、これらの製品群は既存ネットワークインフラを席巻していくことになると思います。
これらへの移行の足かせとなるのは既存の様々なSaaSに施されているGIPによるアクセス制御です。
すべてのSaaSに対して、GIPの再登録を余儀なくされます。

#GIPのアクセス制限の本質
そもそもGIPでアクセス制限した場合に守れるもの、守りたいものはなんでしょうか。
理由は以下のものになると思います。

* 社外からのSaaS利用の拒否
* SaaSを外部攻撃から守る

どちらの理由もよく考えるべきだと思います。

1つ目は、社外からSaaSを使えちゃまずいんでしょうか。
社員を信頼できない信頼関係が悪いと考えます。
どうしてもやりたいのであれば、Azure ADや前述のSD-WANなどの仕組みでアプリケーションへのアクセスを制御すべきです。

2つ目は、攻撃から守るのは利用者側の責任でしょうか。
SaaSの防御は、SaaSを提供している事業者が対応すべきではないでしょうか。
GIP制限をかけないと攻撃を防御できないSaaSであれば、違うSaaSを使うべきです。

#それでもやったほうがいい場合もある
以下のような場合には、GIPによるアクセス制限は引き続き実施すべきと考えます。

* インターネットへ開かれていない、特定の場所へ向けたサービス
* 検証環境、開発環境などの脆弱であることをすでに認知しているサービス

#GIPによるアクセス制限はやめましょう
そろそろ、やめましょう。
働き方が自由になり、ネットワークインフラが足かせにならないように。
異論は認めます！
DockerのDBとしてPostgreSQLを使用した際に躓いたところ

## エラー経緯、内容
アプリのDBとして、docker上でPostgreSQLを動かすように`docker-compose.yml`を以下内容で作成。

```rb:docker-compose.yml
version: '3.1'

services:
  database:
    image: postgres
    restart: always
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: root
```

その後`migration`を実行すると

```rb
FATAL:  role "root" does not exist
```
というエラーが発生。

## 解決策
### 結論
`root`のロールを作成し、必要な権限を与える
### 具体的にやったこと
`psql`コマンドでDBの起動状況を確認します。

```terminal:terminal
psql -l
```
`Owner`欄に`root`がないため、そもそもロールにrootの登録がなし。

したがって、まずはrootのロールを作成します（`docker-compose`の設定に合わせて`password`も設定）。

```terminal:PostgreSQL
postgres=# CREATE ROLE root WITH LOGIN PASSWORD 'root';
```
その後、psqlコマンドで何でも良いのでDBに接続し、ロールの情報を表示させます。

```terminal:PostgreSQL
postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 postgres  | Superuser, Create DB                                       | {}
 root      |                                                            | {}
 tomokazu  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
```
これを見ると、`Role name`が`tomokazu`である場合にのみ、`Create role`の権限が付いているため、`tomokazu`のロールで作成されたDBにどれでもいいので接続し、rootのロールを作成します。

```terminal:terminal
psql -U tomokazu -d postgres
```
接続後、`ALTER ROLE`コマンドで権限を付与します（`CREATE ROLE`時に権限も同時に付与できそうなので、それでも良いと思います）。

```terminal:PostgreSQL
ALTER ROLE root SUPERUSER CREATEDB;
```
もう一度`\du`でロールの設定一覧を確認すると、

```terminal:PostgreSQL
postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 postgres  | Superuser, Create DB                                       | {}
 root      | Superuser, Create DB                                       | {}
 tomokazu  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
```
ということで、めでたくロール`root`の作成と権限付与が完了。

もちろん、問題なくdocker上でPostgreSQLを使えるようになりました！

## 覚えておくべきこと + 疑問点
### 覚えておくべきこと
あまりPostgreSQLを使っていないせいか、まず何のコマンドで動作状況なり、DB接続等を行うのかわからなかったため、以下コマンドはざっくり覚えておこうと思います。

```terminal:terminal
psql -h [ホスト名] -p [ポート番号] -U [ロール名] -d [DB名]

# つまり具体的にはこんな感じ
psql -h localhost -p 5432 -U postgres -d postgres
```

### 疑問点
ローカル側のpsqlコマンドにてrootのロールを作成し、必要な権限を設定したのですが、なぜ`docker上`のpsql操作ではなく、`ローカル側`で良かったのか？
docker設定の細かな内容が理解ができていないのか、
はたまたPostgreSQLの動きを理解できていないのか、引き続きその理由を調査する必要があるなあと感じました。
metaを用いたページの自動遷移メモ（デプロイ後URL有）

3秒後に、指定のリンク先のURLに自動遷移させたい場合は下記の様なコードを記述する。

```ruby:htmlファイル
%meta{content: "3;URL=指定のリンク先のURL", "http-equiv": "REFRESH"}
```
【調査メモ】SnowflakeにてユーザーへのMFA（多要素認証）の自動設定について

## 調査結果
2020年6月1日時点では、Snowflakeにて、ユーザーへのMFA（多要素）の認証の自動化を実施できないようです。
根拠は下記記載内容ですので、最新情報はドキュメントをご確認ください。
> ただし、現時点では、ユーザーは自動的に MFA に登録されません。MFA を使用するには、ご自身でご登録ください。

引用元：[多要素認証（MFA）](https://docs.snowflake.com/ja/user-guide/security-mfa.html)

## 関連情報
"ALTER USER"にて、"DISABLE_MFA"というプロパティがあるのですが、無効化を実施するだけのようです。
> ユーザーの MFA を無効化して、登録を事実上キャンセルします。MFA を再度使用するには、再登録する必要があります。

引用元：[多要素認証（MFA）](https://docs.snowflake.com/ja/user-guide/security-mfa.html)


## 私見
”現時点では”との記載から、今後は自動で付与できるようになるのかもしれません。
Chart.jsでレーダーチャートのラベルの文字表示

シンプルなメモ。

Chart.jsは便利なのですが、細かいサイズや色調整をしようとすると、なかなか目当ての記事にたどりつきにくい。

特に、レーダーチャートのようなあまり使わないものの記事は見つかりにくい。

http://www.kogures.com/hitoshi/javascript/chartjs/radar.html

細かいサンプルが載っていた良いページを見つけたので、振り替えられるようにメモ。
vscodeのros拡張機能でモデルプレビューしながらurdf編集まで

vscodeのインストールから以下の画面に至るまで。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260065/08e9e6b3-c187-976b-772c-053ac87dd65d.png)


# 環境
- Ubuntu 18.04

# vscodeのインストール

まずはvscodeのインストール

```
$ sudo snap install --classic code
```

<!-- 
snap:コマンド名であり、パッケージ形式のこと。
古い環境に新バージョンのソフトウェアを提供したいが、debパッケージでは依存関係が解決できない。
解決手段として、必要なものを丸ごとパッケージして、他のパッケージとの依存関係を気にせずに済むようにしたもの

snapパッケージのセキュリティーの仕組みにより、snapアプリケーションは既存のシステムから切り離されて配置されるため、
ユーザーは他のアプリやシステムに与える影響を心配すること無く、snapアプリケーションをインストールできる。
-->

# vscodeの起動

以下のコマンドで起動

```
$ code
```

# 拡張機能のインストール

vscode上で Ctrl + Shift + X でExtensions marketplaceを開く。
rosと検索して一番上に出てくるやつをinstallボタンでインストール。

Ctrl + Shift + Pでvscodeのコマンドパレットを開いて、rosと入力するといろいろコマンドが出てくる。
ROS: Preview URDF がurdfをプレビューするやつ。

ただし、ワークスペースを開いてやらないと以下のようなエラーが出る。（補足[1]）

```
Command 'ROS: Preview URDF' resulted in an error (command 'ros.previewUrdf' not found)
```

vscodeのウィンドウにワークスペースのディレクトリを追加してやろう。
なので、urdfファイルを開くときに以下のように指定してやる。

```
$ roscd urdf_tutorial/
$ code urdf/01-myfirst.urdf -a ~/catkin_ws/
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260065/ff3495a7-76d9-df86-e30a-87f9846f913c.png)



xacroファイルもいける

```
$ code urdf/08-macroed.urdf.xacro -a ~/catkin_ws/
```

少し読み込みに時間はかかる、
プレビュー画面をクリックすると読み込む気がする。気のせいか
読み込むまでは以下のように空間が表示されるだけ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260065/56df692e-eafc-77e1-38e9-9fb23aafb4cc.png)


ちゃんと表示された。
便利だね

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260065/e213e177-d7a1-f6b7-e827-f5a2703265b6.png)


<br><br><br>

# 補足

[1]これは
/home/user/.vscode/extensions/ms-iot.vscode-ros-0.6.3/package.json
の以下の部分の記述がある。(62行目)
catkinワークスペースにいればアクティブ化されるってことかな

```package.json
// Activate if we're in a catkin workspace.
let buildToolDetected = yield buildtool.determineBuildTool(vscode.workspace.rootPath);
if (!buildToolDetected) {
    return;
}
```
JetsonNanoにOpenCVをインストールする方法　Python

#0.最初に
今回はYoutubeに上がっていた[こちら](https://youtu.be/tFGZjVUR_Ck)の動画を参考にしてインストールします。
#1. OpenCVのインストール
まず、github上のレポジトリをクローンします。
```git clone https://github.com/JetsonHacksNano/buildOpenCV
```
![opencv1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616944/66a10eac-79a8-3884-e285-a588b113084f.png)
それが終わったら他のディレクトリに移動します。
```cd buildOpenCV ```
![opencv2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616944/65f7cfe9-99d1-8ac0-8355-caca858ab3cd.png)
そして、インストールを開始します。
![opencv3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616944/72e322e1-188d-899b-5787-f896f56e2fd8.png)
やはり、途中で画像の右上のようにLow Memory Spaceとでてきてしまいます、、、
そのため私はいくつかのファイルを消しました。
![opencv4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616944/8e2b9b42-a27e-87c4-7cdf-1239f3212ea2.png)
そして、ようやくインストールが完了
![opencv5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616944/8469ac93-2e2e-0502-ab76-c021ea7353aa.png)
結局、1時間30分ほどかかりました。
![Screenshot_20200601-142539.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616944/db77793f-c1ab-5310-d7f7-dceb795c3731.png)
そして、下の画像からわかる通りPython2.7とPython3.6ではインポートできますが、Python3.8ではできませんでした。
![opencv7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616944/a9881797-d58d-7acc-c348-e5a6eafc71ee.png)
#2.OpenCVの動作確認
OpenCVを使ってこの画像をネガポジ反転させてみると、
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616944/8aa7d12e-b372-8dba-2d07-052df58be52e.png)
しっかりネガポジ反転ができました！！！
これでOpenCVのインストールは成功です。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616944/4fcf9905-62f5-a710-d05c-a4efbf77cab0.png)
#最後に
[Youtube](https://www.youtube.com/watch?v=wDMue0R7aBg)でpythonを使っていろいろ解説しているので良かったらご覧ください。質問等がござコメント欄でどうぞ。また、いいなと思ったら[チャンネル登録](https://www.youtube.com/channel/UCDYbu9aViDvkubFcwgbbKDA)お願いします。
`if (a == 1 && a == 2 && a == 3)` は真か？

## 背景
なんだか面白そうな記事を見つけた
[（a == 1 && a == 2 && a == 3）は真と評価できますか？](https://www.it-swarm.dev/ja/javascript/（a-1-ampamp-a-2-ampamp-a-3）は真と評価できますか？/836583231/)
のでSwiftでやってみた

## コード
```swift
var b = 0

var a: Int {
    get {
        b += 1
        return b
    }
}

if (a == 1 && a == 2 && a == 3) {
    print("Complete!")
}
```
### 解説
`a`とは別で変数を用意(ここでは`b`)して、`a`のgetterで`b`をインクリメントし、`b`をreturnする。
if文で`a`を3回取得するが、その度に`a`のgetterを通るため、取得される`a`の値は1ずつ増えていく。

## 結果
できた。👏
<img width="477" alt="スクリーンショット 2020-06-01 14.53.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532881/a050df8d-ad53-d33d-03dc-4546d4482f1e.png">

## まとめ
getterを使うと、if文の中で同じ変数でも、異なる値を取得できる😳

p.s. 他にいい方法があれば教えてください！
TensorFlowでKaggle Titanicを解く

TensorFlowの公式チュートリアルを見て、あまり丁寧でないと思ったのでKaggle Titanicを題材にTensorFlowの使い方を解説する。
とはいえ僕もまだまだTensorFlowに対する理解が浅いので初歩的な範囲で。

# コード解説
実際にTitanicコンペのために組んだコード（https://www.kaggle.com/yusukemigitera/tf-first ）を解説する。

## インポート、データ整形
ほぼ前回（[2層ニューラルネットワークでKaggle Titanicを解く](https://qiita.com/ysk-cpu/items/2e569d76f96289578cac)）と同じ。

## 使うデータ項目を選択
今回はPclass（チケットクラス）、Sex（性別）、Age（年齢）、SibSp（兄弟/配偶者の数）Fare（料金）の5項目を利用したが、行列から必要な部分を切り出す方法が分からなかったので一列ずつ削除していった。

```
train_target = train.pop('Survived')
train.pop('PassengerId')
train.pop('Name')
train.pop('Parch')
train.pop('Ticket')
train.pop('Cabin')
train.pop('Embarked')

train_array = np.asarray(train.values) #Numpy配列にする
target_array = np.asarray(train_target.values) #Numpy配列にする

dataset = tf.data.Dataset.from_tensor_slices((train_array.astype('float32'), target_array))
# TensorFlowで扱いやすい形の変数におく
```
また、`np.asarray()`や`.astype('float32')`でデータ型を指定しなければよく分からないエラーが起きる。

## モデル定義、学習
```
model = tf.keras.Sequential([
    tf.keras.layers.Dense(10, activation='relu'),
    tf.keras.layers.Dense(10, activation='relu'),
    tf.keras.layers.Dense(1, activation='sigmoid')
])
```
`tf.keras.Sequential`というクラスのインスタンスを作る。引数に入れた配列の要素`tf.keras.layers.Dense()`がニューラルネットワークの層を表す。`Dense`は全結合の層で、(ノード数, 活性化関数)をその引数で指定する。

入力層はこれに含めず、上から中間層2つのノードが10個ずつ、出力層のノードが1個のニューラルネットワークを定義している。

分類問題は出力層に分類の数と同じノードを用意するものだが、ここは[公式チュートリアル](https://www.tensorflow.org/tutorials/load_data/pandas_dataframe?hl=ja)の書き方に従った。2値分類はまた特殊なのかもしれない。

```
model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])

model.fit(train_array.astype('float32'), target_array, epochs=15)
```
`compile`メソッドでオプティマイザ、損失関数、メトリクスを設定する。`tf.keras.Sequential`のメソッドについては[Keras Documentation](https://keras.io/ja/models/sequential/)を見ると参考になる。

学習の実行は`fit`メソッドの1行で書ける。この辺はフレームワークの便利さが分かる。

## 推論
```
y = model.predict(test_array.astype('float32'))
```
推論の実行も1行で書ける。

## データを整形してCSVに出力
前回と同じ。

# 評価
![スクリーンショット 2020-06-01 15.02.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501205/9a20d77a-e9e8-2f4c-fa9e-77b608c26c4b.png)
スコアは前回と比べて1%だけ高くなった。まだだいぶ低いが、今回は特に最適化を考えていなかったので仕方ない。
Numpyオンリーで書くよりよっぽど楽。
latexの画像を省略してコンパイルを短くする

graphicxをダウンロードする時に

\usepackage[draft]{graphicx}

とdraftオプションを入れる。

この状態でいつものように画像を挿入する。
すると、画像が枠とファイル名だけになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279062/5eaf02d8-2076-e57a-5ffa-554311125cdd.png)

コンパイルが短くなったぞ

参考文献
https://link.medium.com/HbPGhoujX6
Windows10でBluetoothマウスがしょっちゅう引っかかる問題の対処の顛末

# Bluetoothマウスでポインターを操作しようとすると頻繁に引っかかる

最近のPCはBluetoothが搭載されているのが当然なので、基本的にBluetoothマウスを使っています。USBレシーバを使用するマウスはUSBポートを1つ消費してしまうのが嫌ですし、最近のBluetoothマウスは省電力化が進んでいて、とても電池の持ちがよくなっています。

さて、仕事用のノートPCでBluetoothマウスを使っていると、マウスでポインターを動かそうとした時、動かせるようになるまで1～2秒のタイムラグがあり、引っかかったような状態になる現象が頻発していました。
1～2秒とはいえポインターがすぐに動かないのは非常にストレスフルなので、原因とその対処方法が無いかを調べることにしました。

## 原因は省電力機能にあり

色々と問題の切り分けをして、

 - マウスを替えても同様の現象が発生するので、マウスの問題ではない
 - Bluetoothイヤホンを接続して音楽を流していると、現象が発生しない

という事から、どうやら原因はPCのBluetooth(正確にはそれが接続されているUSB)の省電力機能である事がわかりました。
下記のページを参考に、Bluetoothデバイスの「電力の節約のために、コンピューターでこのデバイスの電源をオフにできるようにする」という項目をOFFにしたところ、ポインターが引っかかる現象はピッタリと収まりました。

 - [Windows 10でBluetoothマウスやキーボードが使えなくなる原因は省電力設定かも](https://solomon-review.net/windows10-bluetooth-peripheral-problem/)

どうやら、省電力のため積極的にBluetoothチップの給電をオフにしすぎているため、ちょっとマウスを使わないだけでBluetoothチップの電源がOFFになり、次にマウスを動かした時に電源がONになるのを待つ必要が出て前述のラグが生じるようです。Bluetoothイヤホンで音楽を流していると常時Bluetoothチップを使っている状態になるため、給電がOFFになることがなく、現象が発生しないわけです。
殆どPCは電源に繋いで使用していますし、そこまでカツカツの省電力は正直不要なので、この項目はOFFで運用することにしました。

## 大型アップデートで再発

この設定変更で幸せになっていたのですが、先日リリースされたWindowsの大型アップデート [Windows 10 May 2020 Update]
(https://www.microsoft.com/ja-jp/software-download/windows10) を適用したところ、問題が再発している事に気づきました。
大方大型アップデートでドライバの設定がリセットされたのだろうと思い、再度前述の設定をOFFにしようと設定画面を開いたところ…

![コメント 2020-06-01 141902.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22414/74d1259f-9c4a-0bb6-c5c5-138e97e774d2.png)

なんと、**「電源の管理」タブが消失**しています。大型アップデートを適用する前は確かに項目が存在していました。
なぜそういう余計なことをするのでしょうか。最近のMicrosoftはイイ感じだったのに、これにはガッカリです。
それはともかく、このままではストレスで禿げかねないので、他の対処方法を探すことにしました。

## 「詳細な電源設定の変更」でUSBセレクティブサスペンドを無効化する

他の対処方法を調べたところ、前述と同様の省電力機能の無効化設定として、「詳細な電源設定の変更」でUSBセレクティブサスペンドを無効にする、という方法があることがわかりました。この設定はデバイス毎ではなく、USBデバイス全体で省電力を無効にする設定になってしまうようですが、背に腹は代えられません。
「詳細な電源設定の変更」は、タスクトレイのバッテリーアイコンの右クリックメニューから「電源オプション」を選択→「プラン設定の変更」→「詳細な電源設定の変更」でアクセスできます。
早速項目を開いたところ…
![コメント 2020-06-01 143317.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22414/7d28e223-8e75-474a-40e2-cac0ebe3f658.png)
またしても項目（USBセレクティブサスペンドの設定が含まれるUSB設定の項目）がありません。どうやらノートPCのベンダーによっては詳細な電源設定の項目を制限しているところがあるようです。

## 設定項目が存在しない場合、「詳細な電源設定の変更」のUSB設定の項目を有効にする

幸い、「詳細な電源設定の変更」のUSB設定の項目はレジストリを変更することで復活させることができます。
**※レジストリの変更は自己責任でお願いします。**
具体的には、レジストリエディタで

 - HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\PowerSettingsを開く
 - その中のキー2a737441-1930-4402-8d77-b2bebba308a3\48e6b7a6-50f5-4782-a5d4-53bb8f07e226を開く（なんじゃこのマジックナンバーは）
 - 右クリック→「新規」→「DWORD(32ビット)値」で「Attributes」という名称の値を作成
 - 「Attributes」をダブルクリックし、値のデータを「2」に変更する

以上の変更を行い、再度詳細な電源設定の変更を開くと、
![コメント 2020-06-01 144420.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22414/0d6dcacf-ae09-b18e-2531-0892d88f4905.png)
無事、設定項目を出現させる事ができました。
この項目の「USBのセレクティブサスペンドの設定」を無効にすることで、再度ポインターがひっかかる現象をなくすことができました。(一応気分的にバッテリ駆動の時は有効にしてあります。)
SwiftUIでScrollViewするときに影が横に出ないなどのトラブル対処法

##この記事で解決できそうなこと
<img width="300" alt="スクリーンショット 2020-06-01 14.25.08.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/291733df-4998-075d-1ed3-38137d0c7c44.jpeg">　　<img width="300" alt="スクリーンショット 2020-06-01 14.30.36.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/afd15274-3b2d-e6bd-b23e-55703af157fa.jpeg">

**せっかく影をつけたのに横に出てないから見栄えが悪い。**
**スクロールインジケータが画面内側に出ている。**

<img width="300" alt="スクリーンショット 2020-06-01 14.33.06.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/8c1db9ec-20fe-174a-00b9-ddb951d6ba38.jpeg">
**画像のような状態を目指します**

##起きている問題の原因
SwiftUIのビューの周りにはframeと呼ばれる外枠が存在します。下の画像のように、デフォルトではビューの周りに存在しています。`frame()`モディファイアは外枠の大きさを変更することで中にあるビューの大きさを変更させるといったイメージですね。
これをスクロールビューで並べると、frameが画面全体に広がっていないので影が外側に出ない、インジケータが画面内に出現するというトラブルが起きます。
 <img width="300" alt="スクリーンショット 2020-06-01 14.36.13.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/7482035e-cec9-3dae-d22d-6e682677809b.jpeg">

##問題の解決方法
`padding`モディファイアによってframeをビューより大きく設定する必要があります。
<img width="477" alt="スクリーンショット 2020-06-01 14.35.59.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/0537aaab-612a-b607-866e-3aa8d782a55b.jpeg">
`.padding(.init(top: 0, leading: 50, bottom: 0, trailing: 50))`
のように、中身のビューのどのくらい外に外枠を配置するのか設定することができます。

##ソースコード
**padding``をコメントアウトすることで横に影が表示されるようになります。

```Swift
import SwiftUI

struct test: View {
    var body: some View {
        ScrollView{
            VStack(spacing: 8){
            ForEach(0..<15){ _ in
        Text("Hello, World!")
            .foregroundColor(.white)
            .frame(width: 300, height: 60)
            .background(Color.yellow)
            .padding(.init(top: 0, leading: 50, bottom: 0, trailing: 50))
            .shadow(radius: 10)
                }
            }
        }
    }
}

struct test_Previews: PreviewProvider {
    static var previews: some View {
        test()
    }
}
```
[Swift] クロージャ（Closures）の記法

クロージャ（Closures）ってなんだか色々書き方あってややこしいですよね。
というわけで整理してみます。

## 想定読者
* Swiftの基本的な文法はなんとなく理解しているが、クロージャはややこしいな、という人
  * Swiftはある程度書けるようになったけど、いまいちクロージャの書き方に自信がない人
  * 他言語でプログラミング経験があり、これからSwiftを学びたい人

## クロージャとは
> Closures are self-contained blocks of functionality that can be passed around and used in your code.
> Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages.

https://docs.swift.org/swift-book/LanguageGuide/Closures.html

> クロージャは、コードの中で渡したり使用したりすることができる自己完結型の機能ブロックです。
> Swiftのクロージャは、CやObjective-Cのブロックや他のプログラミング言語のラムダに似ています。


## クロージャの書き方
### 基本構文（全部盛り）
まずはこれをしっかりと覚えると、後に紹介する省略記法が理解しやすくなります。

```
{ (引数名1: 型, 引数名2: 型...) -> 戻り値の型 in
     実行するコード...
} 
```

#### 例
```swift
// 定義
let intToString = { (a: Int, b: Int) -> String in
    return "\(a)と\(b)です"
}

// 利用する
let sample1 = intToString(1, 5)
print(sample1) // 1と5です

```

### 省略
#### 型表記
型が推論できるケースでは、引数や戻り値の型表記を省略できます。

* 型が推論できるケース
  * 代入する変数の型が明確
  * 関数の引数（関数定義で明確に記載される）

```swift
// 代入する変数の型が明確
var sample2: ((Int, Int) -> String)

// 引数の()も省略可能
sample2 = { a, b in
    return "\(a)と\(b)です"
}

print(sample2(2, 3)) // 2と3です
```

#### return
クロージャ内の文がひとつしかない場合は `return` 省略可能

```swift
// return省略
let intToString = { (a: Int, b: Int) -> String in
    "\(a)と\(b)です"
}
```

下記コードはコンパイルエラーとなります。

```swift
// 2つ以上文があると省略不可
let sum = { (a: Int, b: Int) -> Int in
    let sum = a + b
    sum
}

// ;で1行にしてもダメ
let sum = { (a: Int, b: Int) -> Int in
    let sum = a + b; sum
}
```

### Shorthand Argument Names
型表記を省略できるケースでは、さらに引数名も省略可能です。
`Shorthand Argument Names` は `$` に引数のindexを合わせ、`$0` や `$1` と記載します。

```swift
// 引数名も省略可能
// 型の表記も省略 -> in も省略しないとコンパイルエラー
sample2 = { 
    "\($0)と\($1)です"
}
```
ロードマップ


## 資格を取る

直近以下3つの資格を取得する。
一つレベル的には低いが、特に資格をなにか持っているわけでもないので。。。
技術力の底上げのため、資格取得をしていきたいと思う。

|受験月|項目|
|---|---|
|2020/07|AWS Solution Architect(Associate)|
|2020/09|Certified Kubernetes Administrator (CKA)|
|2020/10|Certified Kubernetes Application Developer (CKAD)|


## 試験までの記録(AWS Solution Architect(Associate))
### 参考文献
- [AWS認定ソリューションアーキテクト](https://www.amazon.co.jp/dp/B07R1H87Y1)

### ロードマップ
week1: 1日1章ずつ完結させる
week2: 1日1章ずつ完結させる
week3: 1日1回テスト問題をして振り返る
week4: テスト当日

## 試験までの記録(Certified Kubernetes Administrator (CKA))
### 参考文献
- [Certified Kubernetes Administrator (CKA) 受験ログ](https://qiita.com/sotoiwa/items/3509ca3d18d1bed00dee#%E3%81%9D%E3%81%AE%E5%BE%8C)


## 試験までの記録(Certified Kubernetes Application Developer (CKAD))
### 参考文献
- [Certified Kubernetes Application Developer (CKAD) 受験ログ
](https://qiita.com/sotoiwa/items/70cf93ebe2718a3be6b3)
セルカウント健忘録

ど素人は忘れ易いのでメモ書き

環境
windous10 home(64bit)
anacondanavigator
Jupiternotebook
python3(3.7.7）
opencv(3.4.2)

やりたい事としては粒(粒子)の数を数えるプログラムを作成したい。
ちなみに初学者。
周囲に教えてくれる人はいないので独学。
おかしい箇所は多々あります。

参考文献
https://cvtech.cc/count/
C++用なのでpythonに合わせるのに苦労しました。

使用画像としては上記参考文献に倣い種画像を使用。
![seed.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607764/8b9f4ecb-8d33-9a5c-27a8-631ab44dc4c5.jpeg)


## 使用ライブラリ
```python:cell_count.ipynb
import cv2
import sys
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
```
ぶっちゃけopencvとnumpyだけで事足りますが
自分の中でベーシックセットしてpandasとmatplotlibを足しているだけです。

```python:cell_count.iypnb
img = cv2.imread('/seed.JPG',1)
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
```
上段はカウントしたい画像
下段はグレースケール化したもの。
読込時点で```('/seed.JPG',0)```でもグレースケール化可能と思ったが
エラーが出たのであきらめてグレースケールを追加した。


```python:cell_count.ipynb
size = (800,600)
img_resize = cv2.resize(img_gray,size) 
```
使用画像のサイズが大きいのでリサイズしています。
(単に画面に収まらなかったから…)
画像サイズがそこまで大きくなければ全くいらないと思います。

```python:cell_count.ipynb
#画像の高さ、幅を取得
h, w = img_resize.shape

#画像の前処理(拡大)
mag = 1

#画像の前処理（ぼかし）
img_blur = cv2.GaussianBlur(img_resize,(5,5),0)

#2値画像を取得
threshold = 50
ret,img_th = cv2.threshold(img_resize, threshold, 255, cv2.THRESH_BINARY)

#モルフォロジー変換(膨張)
kernel = np.ones((2,2),np.uint8)
img_th2 = cv2.dilate(img_th,kernel,)

#境界検出と描写
__, cut, __ = cv2.findContours(img_th2.astype(np.uint8),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
img_raw = cv2.resize(img,(w*mag, h*mag))
img_cut = cv2.drawContours(img_raw, cut, -1,(0,255,255),1)
print(len(cut))

```

参考の手順通りに行っていくと画像画像自体が大きくなりすぎて表示しきれなかったので
前処理部分は`mag = 1`にしている(画像自体をリサイズしているから。)

2値化に関しては`threshold = 50`は処理画像を確認しながら自分で思う適切値にしている。

モルフォロジーと境界検出については正直半分も理解していないのが実情…orz
Udemyでの『opencvでの画像処理』講座を参考に何とか書き上げた感じ

`print(len(cut))`はカウントしたarrayを表示させたいので追記。
結果は【475】
ここの部分はtkinter等で表示させる様にしたいが
全くわからんです。

```python:cell_count.ipynb
cv2.imshow("cell",img_cut)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
結果を表示。

![seed2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607764/8a99c06e-21db-0208-d057-09759724f9e1.jpeg)

ここまで来るのに滅茶苦茶苦労したが、何とか望みの画像を得る事が出来ました。

白黒がはっきりとしている画像に対しては問題なく行けるが
粒(粒子)以外に色味があるものに関してはうまくいかなかったので
色成分を抜いての2値化等を試して、絶賛挫折している最中です…( ﾟДﾟ)

tkinterとの組み合わせもしたいが全く知識ないので
覚える事が多くて…(ノД`)・゜・。

以上です。