OpenCVで画像の編集などを学んでみようとしている

openCVを使って手元の画像をちょっとだけ編集などしてみました。

  • 画像の切り取り
  • 画像の色反転
  • 画像から顔を認識するなど

はMatplotlibを利用することですんなりと動かすことができた。 ファイル入力 → 画像から顔を認識し四角で囲む → 編集後の画像を画像として出力する これは簡単にできました。

今回は画像の読み込みと簡単な加工についてです

import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

今回使うのは上記のライブラリを利用しました。

  • openCVを利用。(それはそう。画像だもの)
  • 画像は行列データを含むことがあるっぽいのでnumpy
  • 画像の出力などで利用するのでmatplotlibを

img = cv2.imread('misc/cat.jpeg') 画像の読み込みはopenCVの内部関数'imread'を使い引数に画像を渡してあげるだけで読み込みます。

type(img)
img.shape

などとしてみて画像について確認してみるのも良いですね。

plt.imshow(img) 読み込んだ画像の出力では maplotlibのimshowを使います。 しかしこの状態では画像の色などが想定しているものと違うはずです(後述)

img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)

そこで cvtColor関数にいろを変えるようにお願いします。 これで正常に出力が可能になります。

この原因は OpenCVとMatplotlibの画像を読み込んだ際の色合いの表し方がRGB,なのかBGRなのかというしょうもないもんだいなのですがこれを忘れると画像から生気がきえてしますので注意が必要そう。 (これに気づかず手元でいろいろしたけどググったらすぐに解決した、悲しい)

plt.subplot(1,2,1)
plt.imshow(img)
plt.subplot(1,2,2)

plt.imshow(resizedImg)

このような感じに処理すると一つの描画領域に複数の画像を表示することが可能です。

# gray scale 
grayedImg = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

plt.subplot(1,2,1)
plt.imshow(img)

plt.subplot(1,2,2)
plt.imshow(grayedImg)
plt.gray()

cvtColor関数に'COLOR_RGB2GRAY'を利用すると画像がグレーアウトします。 グレーアウトした画像が欲しい時は便利かも(使う時があるのだろうか)

プログラミング初心者にGitを伝える

TL;DR

プログラミングを覚えこれからどんどん圧倒的な成長をして行くであろう、 モチベーション300%のエンジニアにgitを紹介したい


注意事項

あくまでgitの紹介に重きを置いているのですでにGit使っている人にはお勧めできません、 スッとブラウザバックをお勧めします。

その他・紹介内容にご指摘、提案、補足などあればコメントいただきたいです


余談


スピリチュアルプログラミングとは

コードの持つ本来の力を高める方法論

  • 一心不乱に祈ることでバグ発生率を抑える。
  • バグは作っていない。 俺が最強
  • 徹夜をすると絶対動くんだ。

マインドセット is 大事


開発しんどい

まぁ。ぶっちゃけしんどいときもあります。

  • 自分が実装したいことできないとか。
  • 作りたい機能の設計がうまくできないとか。
  • 実装できたはずなのに動かないとか
  • わけわからないバグとか
  • 意図してないバグとか
  • バグとか
  • bugね。
  • bug
  • bug..bug...bug.....

Debugしましょうね!!!


エンジニアとして業務に触れて察したこと

やればできる。!!

がんばれば、ちゃんと実装できる →楽しいです。 →しんどい分達成感半端ないなぁと。

わかんなかったら近くのできる人に聞けばいいんですよ。 近くのエンジニアはじゃないよ ><!!


agenda

  • git? 何それおいしいの??
  • git使わなきゃダメなの?
  • Let's git !

git? 何それおいしいの??

'\ ok Google! /' git とは


gitは、プログラムのソースコードなどの変更履歴を記録・追跡するための
分散型バージョン管理システムである。

gitでは、全履歴を含んだリポジトリの完全な複製が作られる。
したがって、ネットワークにアクセスできないなどの理由で
中心リポジトリにアクセスできない環境でも、
履歴の調査や変更の記録といったほとんどの作業を行うことができる。
これが「分散型」と呼ばれる理由である。 
                                    from / wiki

え!!!なに!!!!どういうことなの????


難しいことは置いといて。┐(´-`)┌


git is 分散型バージョン管理システム

いいっしょ?良さそうでしょ??? 集中型より聞こえが良いでしょ??????

分散型: Aくん、Bくん、cちゃんがお互いにメモとりあうのと
集中型: Aくんが責任持ってメモをとる

→ Aくんのノートきえたらやばくない????????

いろいろあるんですが。分散型 is Good!!!


git流行ってます

・ git使ってない企業ってあるんですか?
・ 今時git使えないとエンジニアとしてやばいっすよ(偏見)

git 使いましょうよ!!!!!


ほら。ね。流行ってるでしょ。

  > 青git、赤svn、黄色subversion  

gitとは

  • gitめりっと
  • gitの構造理解など。
  • team開発
  • どうしたら慣れて行くのか


メリット


メリット(特徴?)

  • コーディングしている時にSaveができます
    • Pok○m○nのレポートみたいなね。
    • D○rag○nQuestの協会でのお祈りみたいな

gitを使うと好きなセーブポイントからもどれます。

  • ゲームのセーブストックみたいな感じ?
    • メインのセーブデータ:A
    • Aデータ引き継いで別キャラにする: B
    • (A or B)データ引き継いでネカマする用のキャラ

gitの概念


gitの概念

  • Gitってどうなってんの?
  • branch(枝分かれ)というものがある

→みてみましょう。


git とは

localのgit

なんかわかりにくいのでポップなかんじにしましょうか→


ポップなGit

gitの構造について


gitの構造について


branch(枝分かれ)


team開発


gitを使うチーム開発

  • Github
  • bitbucket
  • Gitlab
  • 自前のGitサーバー

等々ありますが、今回はGithubを利用します。


gitとgithub

gitとgithub(リモートリポジトリ)


どうしたら慣れて行くのか


Git、Githubを使うしかない


gitの教材など。

まとめさいと

【初心者向け】Git入門スライドまとめ|基礎から実践まで学びつくそう

Git 教材 Git 教材


Let's git


git config settings

これしとくと便利っぽいので

$ git config --global user.name "<NAME>"
//usernameはWhen,Who,Whatの情報になるので
//GithubAccountName or 本名がおすすめ
$ git config --global user.email "<EMAIL>"
 //gitのusername && email の設定
$ git config --global color.ui auto
 //なんか見やすくしてくれるので

$ git config --global user.name 
$ git config --global user.email 
 //->ちゃんとひょうじされていればおk

git command not found ってなる人は win : https://www.granfairs.com/blog/cto/install-git-for-windows https://www.granfairs.com/blog/cto/install-sourcetree-for-windows

mac: https://qiita.com/takm-reason/items/1c368d14a76cf1ccedde


では実際に始めましょう

  • まずは作業用のRepoを用意したので下記の準備をしてください
$ cd ~/<dir name>

$ git clone https://github.com/fumihumi/git_practice_repo.git

  //githubにsshkeyを登録している場合はっsshを使ってください

$ git branch
// masterを確認
$ git branch <your name> // branch作成
$ git checkout <your name> //Branchの移動
$ git branch
// 変わってることを確認
$ mkdir <your name>
$ cd <your name>
  // ex:$ git checkout -b fumihumi
  //    $ mkdir fumifumi
  //    $ cd fumihumi

ここから先 \<fumihumi> → yourname に読み替えてください。(疲れたw)

touch sample fumihumi.html

コピペ用


$ git add fumihumi.html
作業ツリーのファイル
→ 右側の `Hunkをステージへ移動`

git add


$ git commit -m 'fumihumi.htmlの作成とテンプレの作成'
$ 左上のコミットからメッセージ入力してコミットボタン

git commit


基本的な操作はこれだけです。

for (var gitExp = 1; gitExp < '覚えるまで'; gitExp++){

-> [Bootstrap入れましょう](https://gist.github.com/fumihumi/54ca0eda54be625ca554b4dc355904f1#file-2-bootstrap)

Add -> Commit

→ [bootstrap使ったボタン置いてみる?](https://gist.github.com/fumihumi/54ca0eda54be625ca554b4dc355904f1#file-3-bootstrap4)

Add → Commit

→ [ButtonClickでAlertしてみて](https://gist.github.com/fumihumi/54ca0eda54be625ca554b4dc355904f1#file-buttonclick-alert)
//javascriptコメントアウトの構文も調べて見てね  : ヒント(ES6 ,AllowFunctions, Variables Scope)

Add → Commit

}

基本的には上記のような add -> commit が基本原則。

gitの構造について

時々右から左のようなコマンドもありますが。うまく使ってればそう必要にならないので今回は深く説明しないので口頭で。

$git reset --hard HEAD^
$git reset --mixed HEAD^ (--softもあるよ)

$git rm <file name>

github

github


git clone をしているとCloneした場所がリモートリポジトリになっています。
→みんなのRepoはgithub.com/fumihumi/git_practice_repo,を見ています。

$ git remote -v 
で確認できるので見て見てください。

このリモートリポジトリにさっきまで編集していた,
Commitを反映することを'Push'
リモートにある変更を受け取ることをpullと言います。

$ git push  

git push --set~~~~~みたいなメッセージでたらそれに従ってください


github上でリポジトリ管理者(ここではfumihumi)にコードを受け入れてもらおう!(PullRequest!)


PRが作られたら -> きっとコメントやなにかをもらうかもしれない → masterBranchにまーじ(統合)されたら開発しゅうりょー \(^o^)/

目を通して見ると雰囲気わかると思います。 英語のコメントや issue で頻出する略語の意味 (FYI, AFAIK, ...) コードレビューを受けるのがつらくなったときは コードレビューの辛さと大切さ コードレビューの際に気をつけること


今回は自分のRepoを使い’git clone’しましたが、じっさいに行う際はこんな感じです↓


## 先にGithubのRepoを作っておく

$ git init #ローカルのgitリポジトリ作成

$ git remote add  "alias" URL (remote repo の登録)
$ git remote -v

$ git status (states of this directory-tree )
$ git add ~~~ (adding staging area)
$ git commit -m'commit message' (commiting file && message)

git push (to pushiing remote repos)

branchの考え方


その他, コマンドを知っているともっとgitが便利に使えます。

git log
git status
git stash
git reset
git rm
git revert
git rebase
git show
git branch
git checkout
git log --oneline --decorate --graph

今回触れていないコマンドもいっぱいあるよ!↓↓↓↓↓ GIT CHEAT SHEET

意外と知らない? Gitコマンド 100本ノック


Gitはとても奥が深いです。実際に触って苦しんでいるときに成長します


Let's gït lífè


readmeにおける画像出展

TKRさんQiita:引用よく使うGitコマンドを図解

あさちゅんのブログ

A successful Git branching model

A successful Git branching model(翻訳版)

こっそり始めるGit/GitHub超入門(終)

はじめようgit

いつやるの?git

rails db:migrate:status に "******no file ********"がある時

title通り

rails db:migrate:status に "no file **"がある時 の対処について考えてみます。

すでに本項目の対処記事というものは上がっておりますが 僕の環境では一箇所詰まってので改めて記事にしています。

そもそも絵タイトルの状態 is 何?という人は rails アプリケーションディレクトリにて rails db:migrate:status もしくは rake db:migrate:status と実行してみてください。 過去に.....pending migrations error.....とかをみていたりすると このコマンドしっているんじゃないかなと思いますが、、、

下記のような結果が帰ってくると思います。 gyazo.com

それぞれが何を意味しているのか。。。 status →migrationファイルの実行状況です。upとされていれば該当migrationファイルは実行済みとなっています。  逆にdownになっていれば、そのmigrationファイルは未実行状態なのでファイル編集や削除等を気兼ねなく行えます!

migration_ID →こちらは rails g migration ~~ というコマンドを実行した際のタイムスタンプになっています! UTCを基準にスタンプしているようです。  基本的に 年月日、~時~分~ 秒という単位になっているので同じタイムスタンプがつくことはまぁ、ないでしょう

MigrationNAME →migration name というのは該当migrationファイルの名前(クラス名)です

ところで、本記事をみているということはmigrationで何かミスを犯したということですね???????

→執筆時点で私もミスをしていましたが。.......w

基本的に status が upになっているmigration ファイルの削除、及び変更は禁止 です! これはrails のmigrationの実行状態は db/schema.rbというファイルにて管理しています。 shcemaファイルというのはとても重要になっており。 migrationファイルの実行によって書き込まれ、同時にrailsmysqlsqliteといったdatabaseへtable作成、レコードの(追加|削除|など)といったSQLの発行をしています。

つまり、migrationファイルを実行した後はDBへの命令も実行がされています! その状態でmigrationファイルを削除したり、編集してしまうとmigrationファイルと,db/schema.rbの整合性がうしなわれてしまうのですorz。。。。。。。

※特にアプリケーションをデプロイする予定がある人などはmigrationファイルは綺麗に管理しておいた方が良いですね。 →上から順番にmigarationを実行する際に整合性が失われていると rake abortとなり、えらー解決をしないといけません。.......(こいつがめんどくさい)

ではno fileとなってしまったらどうしたらいいのか!

方法としては、nofileとなっているmigrationファイルをコマンド等を利用して、ファイルを作成します。 DBに対して何も命令をしないmigratioファイルを作成 そのファイルのstatus を downに変更 →うまくいったら削除。 というのが全体の流れです!

対処。

gyazo.com このnofileになっているファイルの注目すべき箇所はmigration_idです。

20171010091337 となっていますね。 本来であれば、~1010091337となっているファイルがあったはずなのに、何かの拍子に消してしまったと… (過去の大罪ですね…)

ではこのNofileとなってしまっているマイグレーションの齟齬を合わせるためのtmpファイルを作成し、DBに変更を加えないファイルを作っていたあげればよい。というのが本案件の解決策です。

cd db/migrate touch ~さっきのマイグレーションid~_tmp.rb(下記) そしてエディタ、(vim等)で編集していきます。

class Tmp < ActiveRecord::Migration[5.1]
  def change

  end
end

はい。こちらのように変更した後で

rails db:migrate:status として見ると、Nofileとなってしまっていた箇所が tmpファイルに置き換わっています!

次は、そのふぁいるをrollbackしてあげればいい。

rails db:rollback もしくは

rails db:migrate:down VERSION=[バージョン番号]

のようにしてあげれば良いのです。

正常に動作すると

rails db:migrate:status と実行すると "no file **" このmigrationファイルがdownになってると思われます それをコマンドないしfinderなどから削除してあげれば対応完了です

n番煎じのような記事になってしまいましたがfumihumiサクッとメモでした

javascriptで Document.getElementByXpath で検索したかった。

javascriptXpathで検索したかった。

普段rubyでscrapingやcrawlerをつくるなどするときはRubyGemsの'capybara,Nokogiri,Mechanize'といったものを利用しているため大抵のDocument検索はXpathをつかって検索していました。

久しぶりにJavascriptを使ってJSを書くとき。 'あの要素Xpathでとれないかなと思い'おもむろに

document.getElementByXpath()

と実行したところ

VM324:1 Uncaught TypeError: document.getElementByXpath is not a function
    at <anonymous>:1:10

そんなものないよと怒られた。

G先生にきくと下記のようなfuncを定義すれば良いとのことなのでこれを使ってあげれば JavascriptにてXpathで要素取得が可能になります。

function getElementByXpath(path) {
  return document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}

-----追記

Githubで同じようなことをやっている人がいないかなと思い、検索したらまとめてる方がいました。

gist.github.com

document.getElementByXPath = function(sValue) { var a = this.evaluate(sValue, this, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); if (a.snapshotLength > 0) { return a.snapshotItem(0); } };
document.getElementsByXPath = function(sValue){ var aResult = new Array();var a = this.evaluate(sValue, this, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);for ( var i = 0 ; i < a.snapshotLength ; i++ ){aResult.push(a.snapshotItem(i));}return aResult;};
document.removeElementsByXPath = function(sValue) { var a = this.evaluate(sValue, this, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for ( var i = 0 ; i < a.snapshotLength ; i++ ) { a.snapshotItem(i).parentNode.removeChild(a.snapshotItem(i)); } };

---追記終わり

fumihumiサクッとメモでした。

参考: stackoverflow.com

追記

chromeにはwindow.$x というものがあり、

ƒ $x(xpath, [startNode]) { [Command Line API] }

となっていました。

ブラウザで検証等を使って試す時は

$x(xpath)

で良いようです。(chrome, safariにて動作を確認しました)

web ViewでなんちゃってPWAを作ってみた。 ~javascript alert()が動かない~

PWAとは

..progressive web apps

とよばれるアプリケーションですね。詳しいことは割愛しますが。基本的には ブラウザ最強! ネイティブアプリいらなくね?????? というような思想(違う)というものです。。

ただ、iOSsafariでは、まだPWAの基盤になりうる、push通知やservice worker などがまだ実装されていないのです。

そこで今回はwebViewにしてみました。 その際のTipsを軽くまとめます。

javascript の alert関数や comfirm のウインドウが開かない

今回は該当のVC (WebViewを使っているVC) に対してWKUIDelegateを使いjavascriptがうまく動くように実装します。

extension SampleViewController: WKUIDelegate {
    
    // alertを表示する
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        
        let alertController =
            UIAlertController(title: "", message: message, preferredStyle: .alert)
        
        let okAction =
            UIAlertAction(title: "OK", style: .default) { action in
                completionHandler()
        }
        
        alertController.addAction(okAction)
        present(alertController, animated: true, completion: nil)
    }
    
    // confirm dialogを表示する
    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
        
        let alertController =
            UIAlertController(title: "", message: message, preferredStyle: .alert)
        
        let cancelAction =
            UIAlertAction(title: "Cancel", style: .cancel) { action in
                completionHandler(false)
        }
        
        let okAction =
            UIAlertAction(title: "OK", style: .default) {
                action in completionHandler(true)
        }
        
        alertController.addAction(cancelAction)
        alertController.addAction(okAction)
        
        present(alertController, animated: true, completion: nil)
    }
    
}

このようにすることで alert(), comfirm()が正常に動くようになります。

why ?

webViewは基本的にブラウザのWindowを一つしか描画しないようです。

しかしながらJavascriptを利用すると、ブラウザはalert用のwindowを新規に作成します。 つまり、本来であればブラウザの中に別のwindowを展開するのですが、webviewではそれが不可能なので、 swiftの alertViewを利用してalertを表示するようにします。

こうすることでwebViewにてjavascriptのalert, comfirmが動くようになります。

インジケータを出したい。

extension SampleViewController: WKNavigationDelegate {
    
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        UIApplication.shared.isNetworkActivityIndicatorVisible = true
        showIndicator()
    }
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        UIApplication.shared.isNetworkActivityIndicatorVisible = false
        self.view = webView
        self.indicator.stopAnimating()
    }
    
}

こうすることでwebViewの中でロードしている最中はstatus bar にてインジケータが出ます。

fumihumiサクッとメモでした。

Podfileを変更したときに’Linker Error’になった。

Podfileを変更したときに’Linker Error’になった。

self.memo for 未来の自分へ

cocoapodにてライブラリ管理をしていると このらいぶらり古いやん。 変更しよ。 となることが多いと思うのですが。その際に下記のようなエラーが出たとき。

clang: error: linker command failed with exit code 1 (use -v to see invocation)

この前にも

ld: library not found

のようなエラーがある、 つまりこの後に続くlibraryが該当プロジェクトにないというエラーっぽい。

GUIでproject→General→ Linked Frameworks and Librariesのところを編集してなかったことが原因でしたとさ。。

podでインストールしたら上記を書き換える人もいるのかなと思います。それを忘れるとエラーになってしまう。

bootstrap4 flexで'wrap'されない

memo

タイトルのような環境にて開発している時に

                <div class="screen-shot d-flex flex-row flex-wrap">
                    <img src='/image/mac_screen_shot.png' class='screen-shot-mac'>
                    <img src='/image/iphone_screen_shot.png' class='screen-shot-iphone' >
                </div>

としていたら思っていた挙動になりませんでした。

これは

flex-row

flex-wrap

この相反する要素が競合していることが原因だと思います。

flex-rowを削除してやることでうまく動くことができました。