Texによる文書作成38 ~電気回路の作図8
今回はTeXを用いた電気回路図の作成のうちの表示について紹介したトランジスタの表示について紹介したい。
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}
さらに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を用いた輪郭近似の続きについて紹介したい。
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について処理をする。
ロゴ画像読み込み、輪郭抽出は前々回を参照。
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')
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点で近似し、曲線の部分に近似点が密集していることがわかる。
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. まとめ
今回は輪郭の特徴量としてモーメント(重心)、面積、周長、また輪郭の近似、バウンダリーボックスについて紹介した。