【CV面経】python+numpyパッケージで1つの画像の2次元ボリュームを実現

15749 ワード

【CV面経】python+numpyパッケージで1つの画像の2次元ボリュームを実現
ある会社を面接するとき、面接官は基本的なアルゴリズムの知識を考察した後、手でコードを引き裂くコーナーに入り、紙とペンを渡して、ボリュームネットワークを書いて、ステップと0を埋めるかどうかは自分で考えますが、ボリューム後のfeature mapとボリューム前の画像の大きさが一致することを保証します.
def Conv2(img,W,H,kernel,3):
	#img:    ;W,H:      ;kernel:   ;3:  3*3  。
	#return:            feature map

親切ですね.フレームワークは全部書いてあります.
通常、1つのボリュームを追加するのはtensorflowを直接呼び出すので、これは确かに私を混乱させて、いつも先にすることはできません:import tensorflow as tf(重要なのは自分が万が一この大杀し器を祭った后に突然tensorflowを追加する関数の呼び出しフォーマットを忘れたことに気づいたのがもっと惨めではありません!)
いずれにしても原理は自分で知っているので、TensorFlowのフレームワークを導入しないつもりで、おとなしく実用的な底辺のpython言語とよく使われるnumpyパッケージを合わせて1つ作りましょう.
まず分析したところ,巻き上げ前後の寸法を一定にするには,外層に0を1周する必要がある.【ここは面接官の小さな穴で、必ず畳み込み前後の寸法を一定に保つには、自分で具体的なpadding数値を計算しなければならない】そこで、まず0を記入するコードを書きました.
    col = np.zeros(H)
    raw = np.zeros(W + 2)
    img = np.insert(img, W, values=col, axis=1)
    img = np.insert(img, 0, values=col, axis=1)
    img = np.insert(img, H, values=raw, axis=0)
    img = np.insert(img, 0, values=raw, axis=0)

次に、本科の時にmatlabでいろいろなボリューム原理と全く同じフィルタを書いたことを覚えています.では、一つずつ来てください.しかし、この知識点は先生に返したような気がします.この時、本科でデジタル画像処理を教えてくれた長龍欧巴附体を心の中で祈っていました.この時面接官は私に書き終わったかと聞いたが、ナニー?これはまだ始まったばかりでいいですか.無理に自分に頼るしかない.
for i in range(H):
    for j in range(W):
        temp = img[i][0]*kernel[0][0]+img[i][1]*kernel[0][1]+img[i][2]*kernel[0][2]+img[i+1][0]*kernel[1][0]……

ああ、待って、ここまで書いて、私はもう自分の背中が冷たくなったような気がします.これは、小さなA 4紙で私の「偉大」な考えを受け入れることができません.自分のコンパイラで、俺の一行のコードを100行に書いたらどうだ?しかし今はだめですね.私が間違っていなくても、この世界が間違っていますが、今は人の地盤にコードを書いています.私たちは人を驚かさなければなりませんか.そこで素早く下の紙を1枚引き出し、pythonスライスで手順を簡略化しました.
temp = img[i:i + 3, j:j + 3]


こんなことを書いたばかりで、面接官はもううんざりしていたので、考えを話してあげました.たぶん見て、「わかりました」と言いました.もう過ぎ去った(率直に言って、自分でも分からないよ.心の中ではもう私を軽蔑しているかもしれないが、私を見ても何も書けないから、メンツをください).面接から帰ってきて、こんな簡単なコードが書けないのは恥ずかしいと思います.そこで自分の縄張りに書いてみましたが、ああ、自分のコンパイラは本当にいいですね......完全なコードは以下の通りです.
#      
import numpy as np

def Conv2(img, H, W, kernel, n):
    # img:    ;W,H:      ;kernel:   。
    # return:            feature map;
    #        3*3  ,           ,            :     1,       0
    col = np.zeros(H)
    raw = np.zeros(W + 2)
    img = np.insert(img, W, values=col, axis=1)
    img = np.insert(img, 0, values=col, axis=1)
    img = np.insert(img, H, values=raw, axis=0)
    img = np.insert(img, 0, values=raw, axis=0)
    res = np.zeros([H,W])##          ,              
    for i in range(H):
        for j in range(W):
            temp = img[i:i + 3, j:j + 3]
            temp = np.multiply(temp,kernel)
            res[i][j] = temp.sum()

    return (res)

if __name__ == '__main__':

    A = np.array([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]])  # 4 5 
    ken = np.array([[2, 2, 2], [2, 2, 2], [2, 2, 2]])
    print(Conv2(A, 4, 5, ken, 3))

最終出力:
[[  8.  12.  12.  12.   8.]
 [ 12.  18.  18.  18.  12.]
 [ 12.  18.  18.  18.  12.]
 [  8.  12.  12.  12.   8.]]

コードにはいくつかの不足があります.
  • ボリュームサイズとステップサイズを変更する場合は、プログラムを再変更します.
  • 画像充填padding書き方少し冗長
  • 画像サイズが畳み込みサイズよりも小さいことを考慮していない
  • .
    最後に、プログラミングは本当に目が高くて手が低い仕事だと心から思っています.自分が料理しすぎたのかもしれません.もともと簡単なアルゴリズムだと思っていましたが、この文章を書くこと、いろいろな関数を調べること、コードを書くことなどを含めて3時間ほどかかりました.
    関連知識点
    一)python行列の各種乗算
    1、np.dot(A, B)または@2 Dマトリクスの場合、これが線形代数のマトリクス乗算です.一方,1次元マトリクスでは,両者の内積が直接計算される.ただし、カラムベクトル(本質的には次元数(1,2)のベクトル)と1次元配列を乗算するとdot関数を使用するとエラーが発生することに注意してください.次のPythonコード:
    A = np.array([[1,2],[3,4]])
    B = np.array([[5,6],[7,8]])
    print("    :",np.dot(A,B))
    print("      :",np.dot(A[0],B[0]))
    
    B1 = np.array([[5],[6]])
    print("   :",np.dot(A[0],B1))
    print("   :",np.dot(B1,A[0]))
    

    出力結果は次のとおりです.
        :array([[19, 22],
           [43, 50]])
    
          :17
    
       :17
    
    ValueError: shapes (2,1) and (2,) not aligned: 1 (dim 1) != 2 (dim 0)
    

    2、np.multiply()または*これはよく理解され,対応する要素の乗算を実現する.やはり上の辺のA、B配列を例にとります.
    print("    1:",np.multiply(A,B))
    print("    2:",A*B)
    

    出力は同じです.
    array([[ 5, 12],
           [21, 32]])
    

    3、array()matrixの違い
    以上はarray()データ型について述べたが,またmatrixのデータ型もあり,乗算面では異なる.具体的なまとめは以下の通りです.
  • array()関数の乗算:*は点乗(対応する要素の乗算)を表し、dot()は行列積を表す.
  • mat()関数の乗算:*は行列乗を表し、multiply()は点乗を表す.この2つのデータ型には他にもいくつかの違いがあり、もう一度まとめる時間があります.ここではこの2つのデータ型を統一することを強く呼びかけています.私は普段array()データ型を使うのに慣れていますが、実は日常の使用でも具体的な区別は必要ありません.乗算を使うときに少し面倒なだけです.点乗はnp.multiply(A,B)行列で乗算します.np.dot(A,B)です.*を使わないでください.

  • 二)numpy行列の和
  • array.sum()行列のすべての要素の合計を計算します.
  • A.sum(axis=0):行列の各列要素の合計を計算します.
  • A.Sum(axis=1):行列の各行の要素の合計を計算します.

  • 三)numpy拡張行列
    方法1
    npを使用する.c_[A,B]およびnp.r_[A,B]行と列をそれぞれ追加
    方法2np.insert( , , values= , axis= )の使用
  • axis=1:列挿入
  • axis=0:行挿入
  • 方法3column_stack((A,B))を使用して列を追加するか、raw_stack((A,B))を使用して行を追加します.
    まとめ:
    この問題はやはり底のコードの実現の基礎を試験して、コンピュータの視覚の職場の学友を面接することに対して、個人はこのような問題が比較的に珍しいと思って、手があれらのカエルを引き裂いて階段を跳ぶなどのアルゴリズムより更に積み重ねに対する理解とコードの実現能力を考察することができて、一石二鳥.これからは面接でよく出るはずなので注意が必要です.
    使用可能なリファレンス:
  • Tensorflowボリューム実装原理+手書きpythonコード実装ボリューム
  • array()とmatrix()の違い
  • について