つれづれなる備忘録

日々の発見をあるがままに綴る

Texによる文書作成38 ~電気回路の作図8

今回はTeXを用いた電気回路図の作成のうちの表示について紹介したトランジスタの表示について紹介したい。

atatat.hatenablog.com

1. バイポーラトランジスタ

バイポーラトランジスタの記号はn型の場合はnode[npn], p型の場合はnode[pnp]とすれば表示できる。 またオプションにphotoを追加して、node[npn,photo]とするとフォトトランジスタを表示することができる。

\begin{figure}
\begin{center}
\begin{circuitikz}

\draw (0,0) node[npn]{};
\draw (2,0) node[pnp]{};

\draw (4,0) node[npn,photo]{};
\draw (6,0) node[pnp,photo]{};
\end{circuitikz}
\caption{バイポーラトランジスタ}
\end{center}
\end{figure}

バイポーラトランジスタ
バイポーラトランジスタ

バイポーラトランジスタのベース、コレクタ、エミッタはそれぞれ名前に.B, .C, .Eを追加することで座標値にアクセスすることができる。 わかりやすくするため例えばベースに抵抗、コレクタにインダクタ、エミッタにキャパシタを接続する場合、

\begin{figure}
\begin{center}
\begin{circuitikz}
\draw (0,0) node[npn, name=T1]{};
\draw (-2,0)[R] to (T1.B);
\draw (0,1)[L] ++ (0,1) to (T1.C);
\draw (T1.E) to [C] ++(0,-1); 
\end{circuitikz}
\caption{トランジスタ接続}
\end{center}
\end{figure}

バイポーラトランジスタの名前をT1として、T1.B,T1.C,T1.Eとするとそれぞれの脚の座標値として使用することができる。

バイポーラトランジスタの接続
バイポーラトランジスタの接続

2. 電界効果トランジスタ

 バイポーラトランジスタと同様にnode[nmos]とするとNチャネル型、node[pmos]はPチャネル型の電界効果トランジスタが表示される。 また、node[nmosd],node[pmosd]は空乏層を太く表示し、node[hemt]はHEMTを表示する。

\begin{figure}
\begin{center}
\begin{circuitikz}

\draw (0,0) node[nmos]{};
\draw (2,0) node[pmos]{};

\draw (4,0) node[nmosd]{};
\draw (6,0) node[pmosd]{};

\draw (8,0) node[hemt]{};
\end{circuitikz}
\caption{電界効果トランジスタ}
\end{center}
\end{figure}

電界効果トランジスタ
電界効果トランジスタ

バイポーラトランジスタと同様に電界効果トランジスタのゲート、ドレイン、ソースはそれぞれ名前に.G, .D, .Sを追加することで座標値にアクセスすることができる。バイポーラトランジスタの例と同様に例えばゲートに抵抗、ドレインにインダクタ、ソースにキャパシタを接続する場合、

\begin{figure}
\begin{center}
\begin{circuitikz}
\draw (0,0) node[nmos, name=F1]{};
\draw (-2.2,0)[R] to (F1.G);
\draw (0,1)[L] ++ (0,1) to (F1.D);
\draw (F1.S) to [C] ++(0,-1); 
\end{circuitikz}
\caption{電界効果トランジスタ接続}
\end{center}
\end{figure}

電界効果トランジスタの接続
電界効果トランジスタの接続

電界効果トランジスタは様々な種類の記号があり、例えばMOSFETで使われる記号はnode[nigfete]で表示できる。

\begin{figure}
\begin{center}
\begin{circuitikz}

\draw (0,0) node[nfet]{};
\draw (2,0) node[nfetd]{};
\draw (4,0) node[nigfete]{};

\draw (6,0) node[pfet]{};
\draw (8,0) node[pfetd]{};
\draw (10,0) node[pigfete]{};

\end{circuitikz}
\caption{電界効果トランジスタ2}
\end{center}
\end{figure}

電界効果トランジスタ2
電界効果トランジスタ2

さらにJFET, pHセンサなどで使われるISFET(Ion Sensitive Field Effect Transistor)やグラフェントランジスタの記号も用意されている。

\begin{figure}
\begin{center}
\begin{circuitikz}

\draw (0,0) node[njfet]{};
\draw (2,0) node[pjfet]{};

\draw (4,0) node[isfet]{};

\draw (6,0) node[pgfet]{};
\draw (8,0) node[pgfet]{};

\end{circuitikz}
\caption{その他電界効果トランジスタ}
\end{center}
\end{figure}

その他電界効果トランジスタ
その他電界効果トランジスタ

3. 円記号の追加

 よくみかけるトランジスタ記号に円(丸)を追加するにはnode[]tr circleを追記するだけでよい。 以下はバイポーラや電界効果トランジスタtr circleを追記して、トランジスタ記号に円を追加している。

\begin{figure}
\begin{center}
\begin{circuitikz}

\draw (0,0) node[npn,tr circle]{};
\draw (2,0) node[nmos,tr circle]{};

\draw (4,0) node[nigfete,tr circle]{};
\draw (6,0) node[njfet,tr circle]{};

\end{circuitikz}
\caption{円記号の追加}
\end{center}
\end{figure}

トランジスタに円を追加
トランジスタに円を追加

最後に追加した円の表示を、塗りつぶし、線色、線種などはctikzset{}でカスタマイズすることができる。

\begin{figure}
\begin{center}
\begin{circuitikz}
\ctikzset{transistors/thickness=4, transistors/fill=cyan!30,transistor circle/relative thickness=0.25,}
\draw (0,0) node[npn,tr circle]{};

\ctikzset{transistor circle/color=red}
\draw (2,0) node[nmos,tr circle]{};

\ctikzset{transistors/fill=none,transistor circle/dash={{2pt}{2pt}}}
\draw (4,0) node[nigfete,tr circle]{};

\end{circuitikz}
\caption{円記号のカスタマイズ}
\end{center}
\end{figure}

円記号のカスタマイズ
円記号のカスタマイズ

4. まとめ

 今回はバイポーラトランジスタ、電界効果トランジスタトランジスタ脚の接続、トランジスタに円記号の追加について紹介した。

OpenCVの使い方27 ~ 輪郭抽出4

今回は前回のOpenCVを用いた輪郭近似の続きについて紹介したい。

atatat.hatenablog.com

1. 円・楕円近似

 円:最小外接円で近似する場合は、cv2.minEnclosingCircleにより中心座標と半径を求める。描画は円を描画するcv2.circleを用いる。

(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
cnt_img = np.zeros_like(gray, dtype=np.uint8) 
cnt_img = cv2.circle(cnt_img,center,radius,255,2)
plt.imshow(cnt_img+cnt_img_tree,cmap='gray')

C字が丸いので、円に対してかなりフィッティングできていることがわかる。

外接円近似
外接円近似

正円ではなく楕円で近似する場合はcv2.fitEllipseを用いる。楕円中心、長軸・短軸長さ、回転角が出力されるが、cv2.ellipseで描画することができる。

ellipse = cv2.fitEllipse(cnt)
cnt_img = np.zeros_like(gray, dtype=np.uint8) 
cnt_img = cv2.ellipse(cnt_img,ellipse,255,2)
plt.imshow(cnt_img+cnt_img_tree,cmap='gray')

C字のくぼみの関係で若干横方向に長い楕円として近似される。

外接楕円近似
外接楕円近似

2. 三角形近似

 三角形で近似する場合は、cv2.minEnclosingTriangleを用いる。三角形の座標が出力されるので、cv2.polylinesで多角形を描画する。

retval, triangle = cv2.minEnclosingTriangle(cnt)
cnt_img = np.zeros_like(gray, dtype=np.uint8) 
tr = triangle.astype(np.int32).reshape((-1, 2))
cnt_img=cv2.polylines(cnt_img, [tr], True, 255, 2)
plt.imshow(cnt_img+cnt_img_tree,cmap='gray')

"三角形近似"
三角形近似

三角形の頂点が収まっていないので、三角形の座標値を調べてみる。

tr
>array([[ 90, 146],
       [285, 146],
       [181, -10]], dtype=int32)

3点目のy座標値が負になっていて、画像の範囲外に近似点があることをあらわしている。

3. 直線近似

最後に直線で近似する場合を紹介する。直線近似はデータ処理の直線近似を画像にあてはめたものでcv2.fitLineを用いることで、傾き(vy/vx)・直線が通過する点(x,y)を用いてcv2.lineで直線を描画する。

rows,cols = gray.shape[:2]
[vx,vy,x,y] = cv2.fitLine(cnt, cv2.DIST_L2,0,0.01,0.01)
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
cnt_img = np.zeros_like(gray, dtype=np.uint8) 
cnt_img = cv2.line(cnt_img,(cols-1,righty),(0,lefty),255,2)
plt.imshow(cnt_img+cnt_img_tree,cmap='gray')

直線近似
直線近似

3. まとめ

 今回は輪郭の近似としてとして円、楕円、三角形、直線について紹介した。

OpenCVの使い方26 ~ 輪郭抽出3

今回はOpenCVを用いて画像の輪郭を抽出する際の特徴量、輪郭の近似について紹介したい。

1. 輪郭の特徴量

画像はOpenCVのモノクロロゴをグレーで読み込み、contoursの11番目の輪郭:下向きCについて処理をする。

ロゴ画像読み込み、輪郭抽出は前々回を参照。

atatat.hatenablog.com

ret,thresh = cv2.threshold(gray,127,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnt_img = np.zeros_like(gray, dtype=np.uint8) 
cnt_img_tree = cv2.drawContours(cnt_img, contours, 11, 255, 1)
plt.imshow(cnt_img_tree,cmap='gray')

"輪郭11"
輪郭11

cntを輪郭11の座標群として、モーメントを算出するにはcv2.moments(cnt)とする。

cnt = contours[11]
M = cv2.moments(cnt)
M

算出されたMを表示するとDictionary形式で、さまざまなモーメントが出力される。

{'m00': 7005.5,
 'm10': 1293147.5,
 'm01': 625488.1666666666,
 'm20': 246294365.91666666,
 'm11': 115440859.95833333,
 'm02': 60851083.916666664,
 'm30': 48267626590.850006,
 'm21': 22035579640.083332,
 'm12': 11228558672.616667,
 'm03': 6346029109.25,
 'mu20': 7591852.64049077,
 'mu11': -18202.06501737237,
 'mu02': 5004185.531108499,
 'mu30': 1305261.314529419,
 'mu21': 51833228.29247081,
 'mu12': -712141.2543185949,
 'mu03': 19321438.742378235,
 'nu20': 0.1546925843274873,
 'nu11': -0.00037088766220471075,
 'nu02': 0.1019659401886588,
 'nu30': 0.0003177602898898274,
 'nu21': 0.012618577954314989,
 'nu12': -0.00017336774552026435,
 'nu03': 0.004703721705013629}

ここで、重心座標を求めたければMを用いて以下のようにする。

cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
print("mom center (",cx,",", cy, ")")

>mom center ( 184 , 89 )

面積はcv2.contourArea(cnt), 輪郭の周長はcv2.arcLength(cnt,True)とすると求まる。

area = cv2.contourArea(cnt)
perimeter = cv2.arcLength(cnt,True)
print("mom center (",cx,",", cy, ")")
print("area:",area, "perimeter:", perimeter)

>area: 7005.5 perimeter: 509.77164113521576

2. 輪郭の近似

 複雑な輪郭を少ない座標点数で近似することができる。輪郭の近似としてcv2.approxPolyDPは指定された長さを最大値として輪郭を近似した場合の近似点を出力する。例えば、輪郭周長の10%を指定して近似を行うと、

epsilon = 0.1*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)
cnt_img = np.zeros_like(gray, dtype=np.uint8) 
cnt_img_list = cv2.drawContours(cnt_img, approx, -1, 255, 5)
plt.imshow(cnt_img_list+cnt_img_tree,cmap='gray')

輪郭の近似
輪郭の近似

元の輪郭を細い線で表してみると、近似点と重なっていることがわかる。なお、指定の長さを短くしていくと元の輪郭に近づく。例えば周長の0.1%(1/1000)で指定すると近似点が増える。近似点が単純に増えるだけでなく。直線のような単純な部分は2点で近似し、曲線の部分に近似点が密集していることがわかる。

輪郭の近似2
輪郭の近似2

3. バウンダリーボックス

単純なバウンダリーボックスはcv2.boundingRectを用いることで、開始座標(左上)x,y, ボックスの幅/高さw,hを出力する。またボックスの幅/高さから輪郭のアスペクト比を求めることもできる。

x,y,w,h = cv2.boundingRect(cnt)
cnt_img = np.zeros_like(gray, dtype=np.uint8) 
cnt_img = cv2.rectangle(cnt_img,(x,y),(x+w,y+h),255,2)
plt.imshow(cnt_img+cnt_img_tree,cmap='gray')
aspect_ratio = float(w)/h
print('aspect ratio:',aspect_ratio)

>aspect ratio: 1.0754716981132075

バウンダリーボックス
バウンダリーボックス

単純なバウンダリーボックスは座標に直交した形で近似するため、輪郭に回転があるような場合は、輪郭に対して大きなバウンダリーボックスが設定されてしまう。回転に対応したバウンダリーボックスはcv2.minAreaRectを用いる。開始座標、幅/高さ、に加えて回転角が出力される。 実際に輪郭11は回転していないので、結果的に単純なバウンダリーボックスと同じになるがcv2.minAreaRect(cnt)の出力は((184.5, 93.5), (105.0, 113.0), 90.0)となる。描画するためには、cv2.boxPointsでボックス4隅の座標点を求めてしまえばよい。

rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
cnt_img = np.zeros_like(gray, dtype=np.uint8) 
cnt_img = cv2.drawContours(cnt_img,[box],0,255,2)
plt.imshow(cnt_img+cnt_img_tree,cmap='gray')

回転バウンダリーボックス
回転バウンダリーボックス

4. まとめ

 今回は輪郭の特徴量としてモーメント(重心)、面積、周長、また輪郭の近似、バウンダリーボックスについて紹介した。