勉強しないとな~blog

ちゃんと勉強せねば…な電気設計エンジニアです。

OpenCVやってみる - 24. Jupyter notebook使ってみた

コマンドプロンプト上でずっとやっているのも大変なので、Jupyter notebookを使ってみました。
見た目もよくなりそう。

Jupyter notebook 使い方

Anacondaをインストールすると、一緒にJupyter notebookが入ってきます。
Windows10環境で使っていますが、検索バーに入力すると出てきました。

f:id:nokixa:20211119032426p:plain:w300

起動すると、いつも使っているブラウザが開きます。
デフォルトではWindowsのユーザディレクトリが開くようです。

f:id:nokixa:20211119032816p:plain:w400

適当な作業ディレクトリを作って移動、New > Python3 と選択すると、新しいノートブックが作成されて開きます。

f:id:nokixa:20211119033030p:plain:w400

f:id:nokixa:20211119033239p:plain:w400

コードを書いて実行できたり、結果の画像もインラインで表示できたりします。
コードを後から書き直して再実行もOK。
なんだかいい感じです。

f:id:nokixa:20211119033410p:plain:w400

はてなブログ

はてなブログにどう貼り付けようかと考えましたが、markdownでのダウンロードが可能だったので、ダウンロードしてコピペすることにしました。

f:id:nokixa:20211119035101p:plain:w400

以下貼り付けします。
画像表示の部分だけは元のmarkdownソースをいじってあります。

~ここから~


使用する画像

春のパン祭り台紙画像を今までにいくつか撮っているので、これらを使います。

import cv2
img1 = cv2.imread('harupan_190428_1.jpg')
img2 = cv2.imread('harupan_190428_2.jpg')
img3 = cv2.imread('harupan_200317_1.jpg')
img4 = cv2.imread('harupan_210227_2.jpg')
img5 = cv2.imread('harupan_210402_1.jpg')
img6 = cv2.imread('harupan_210402_2.jpg')
img7 = cv2.imread('harupan_210414_1.jpg')
img1 = cv2.resize(img1, None, fx=0.1, fy=0.1, interpolation=cv2.INTER_AREA)
img2 = cv2.resize(img2, None, fx=0.1, fy=0.1, interpolation=cv2.INTER_AREA)
img3 = cv2.resize(img3, None, fx=0.1, fy=0.1, interpolation=cv2.INTER_AREA)
img4 = cv2.resize(img4, None, fx=0.1, fy=0.1, interpolation=cv2.INTER_AREA)
img5 = cv2.resize(img5, None, fx=0.1, fy=0.1, interpolation=cv2.INTER_AREA)
img6 = cv2.resize(img6, None, fx=0.1, fy=0.1, interpolation=cv2.INTER_AREA)
img7 = cv2.resize(img7, None, fx=0.1, fy=0.1, interpolation=cv2.INTER_AREA)

Jupyter notebook上に、matplotlibで画像表示してみます。

%matplotlib inline
from matplotlib import pyplot as plt
plt.imshow(img1),plt.title('Image1')

(<matplotlib.image.AxesImage at 0x1d180edf748>, Text(0.5, 1.0, 'Image1'))

f:id:nokixa:20211119040930p:plain

きちんとノート内に画像が表示されています。
matplotlibだとRGBフォーマット前提で表示するので、変換が必要。

以下で色フォーマットを直したうえで全画像表示します。

plt.subplot(241), plt.imshow(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)), plt.title('Image1')
plt.subplot(242), plt.imshow(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)), plt.title('Image2')
plt.subplot(243), plt.imshow(cv2.cvtColor(img3, cv2.COLOR_BGR2RGB)), plt.title('Image3')
plt.subplot(244), plt.imshow(cv2.cvtColor(img4, cv2.COLOR_BGR2RGB)), plt.title('Image4')
plt.subplot(245), plt.imshow(cv2.cvtColor(img5, cv2.COLOR_BGR2RGB)), plt.title('Image5')
plt.subplot(246), plt.imshow(cv2.cvtColor(img6, cv2.COLOR_BGR2RGB)), plt.title('Image6')
plt.subplot(247), plt.imshow(cv2.cvtColor(img7, cv2.COLOR_BGR2RGB)), plt.title('Image7')
plt.show()

f:id:nokixa:20211119040928p:plain

サブプロットタイトルと軸目盛がかぶっちゃったけど気にしない。


~ここまで~

残念なことに見た目はJupyter notebookそのままにはなりませんね。

ここまで

今回はここまでにします。
次回は台紙領域検出をしていきたいと思います。


Jupyter notebook参考

Jupyter Notebook を使ってみよう – Python でデータサイエンス

JupyterNotebook上に画像を表示する2つの方法 | yamagablog

Jupyter Notebookの基本操作とショートカットキー | Python入門

jupyter notebookのサンプルコードをブログに貼り付ける方法を調べた - 子供の落書き帳 Renaissance

OpenCVやってみる - 23. シール点数集計検討

今回はOpenCVネタです。

いままでチュートリアルを追ってきましたが、そろそろ本題の春のパン祭り集計を考えていこうかと。

使えそうな手

今までチュートリアルを見てきた中で、いくつか有用そうなテクニックがありました。

  • 射影変換
    台紙を真正面から撮影していなくても、真正面からの視点に変換できます。
    ロバスト性を上げるのにいいかと。
  • ヒストグラム、2値化
    春のパン祭りだと、年によりますがシールの色が濃いピンク色、台紙はだいたい白となっていて、この色味でシール領域、台紙領域を区別できます。
  • 画像の平滑化
    普通の2Dフィルタだとシールのエッジもぼけてしまいますが、バイラテラルフィルタだといい感じにエッジが残っていました。これも適用しておいてもいいかも。暗いところでの撮影で有効かもしれません。
  • エッジ検出
    Canny法でシールや台紙のエッジが取れますが、その後が難しいかな。次の輪郭検出のほうが使えそう。
  • 輪郭検出
    2値化した後、輪郭情報を得ます。輪郭の面積や外接円などの情報から、それが台紙の外周なのか、シールの外周なのか、といったことが分かります。これは使えそう。
  • テンプレートマッチング
    これは使えそうです。春のパン祭りのシールは0.5点、1点、1.5点、2点、2.5点とある(それ以上ももしかしたら?)ので、それらのテンプレートを用意して一致度を出せば、どの点数か調べることができます。シールを貼るときに傾いたり、そもそも上向きに貼らない人も考えられるので、回転角の考慮が課題かと。
  • ハフ変換による円検出
    シールの領域を探すのに使えるかもしれませんが、上の輪郭検出のほうで十分かな?
  • 特徴量検出、マッチング
    色々やってみましたが、今回は用なしかな。またステレオビジョンなどで使ってみたいとは思います。

方式検討

いくつかのステップを踏む必要がありそうです。

  1. 台紙外形を取得する
    射影変換をするのと、スケーリング(台紙を基準として画像サイズを調整する)に必要になります。
  2. 射影変換実施
  3. シール外形、中心点取得
  4. シール位置でテンプレートマッチング
    テンプレートを回転させながら試す必要がある?

少し考えたこと

  • 自分で撮った画像を見ても、台紙が曲がってしまっていることがあるので、 輪郭検出した後にハフ変換で直線検出をし、4本の直線を検出、その交点を射影変換行列計算に与える点とする、というのでどうだろう?
  • 画像特徴量を勉強したとき、回転不変性を持つ特徴量も紹介されていた。
    今までやったところでは、特徴点を検出してからそこの特徴量を計算する、という形だったが、任意の点から特徴量を計算してもらうことはできるのか?

ここまで

今回はここまでの検討で。
考えたことだけなので面白い記事にはならず…
次回からここで挙げた項目を1つずつ検討していきたいと思います。

ZYBOを進める - 28. Petalinux再設定

前回カスタマイズしたFSBLを作ったので、これをPetalinuxプロジェクトで取り込みます。
また、MACアドレス関連の設定もPetalinuxで行います。
さらについでに、ルートファイルシステムをSDカードに設定します。

Petalinux作業

petalinux-configコマンドを実行して、以下のように設定します。

ルートファイルシステム設定

Image Packaging Configuration ---> Root filesystem type と進みます。
"EXT4 (SD/eMMC/SATA/USB)"を選択します。

f:id:nokixa:20211115024502p:plain:w500

前のツールバージョン(2017.4)では単に"SD Card"だったので、ここはアップデートされているということかと。

Ethernet MAC設定

Subsystem AUTO Hardware Settings ---> Ethernet Settings で、"Ethernet MAC address"を空にします。

f:id:nokixa:20211115024532p:plain:w500

また、U-bootの設定も必要なので、一旦今までの設定を保存してExitします。

その後、以下のコマンドでU-bootの設定を行います。

petalinux-config -c u-boot

設定UIが出るまで時間がかかりますが、表示されたらNetworking supportメニューで"Random ethaddr if unset"のチェックを外します。

f:id:nokixa:20211115024600p:plain:w500

そうしたら保存してExitします。

その後、ビルドとパッケージを実行。
パッケージする際には、前回Vitisで作成したFSBLを指定します。

petalinux-build
petalinux-package --boot --fsbl ../../zybo/zybo-vitis/zybo-fsbl/export/zybo-fsbl/sw/zybo-fsbl/boot/fsbl.elf --fpga images/linux/system.bit --u-boot

この成果物をSDカードに書き込んでZYBOに差し込み、ZYBOの電源を入れます。 シリアル-USBポートもPCにつないで、Teratermを開いておきます。

参考:

How to format SD card for SD boot - Xilinx Wiki - Confluence

Linux起動後、rootユーザでログインしてifconfigコマンドを実行すると、 イーサネット設定が確認できます。

root@Zybo-base-linux-peta:~# ifconfig
eth0      Link encap:Ethernet  HWaddr D8:80:39:5C:83:8B
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:28 Base address:0xb000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

root@Zybo-base-linux-peta:~#

期待通りにXilinxのOUI(先頭3byteが00:0A:35)ではなくMicrochipのOUI( D8:80:39)が確認できました。

以上

前にXilinx SDKでやった手順がVitisでもできるのが確認できました。
Vitisももっと使っていきたい。

次回からはカメラモジュールの続きをやっていこうかと思います。

ZYBOを進める - 27. VitisでFSBL作成

ZYBOの続きです。 今回は、以前にやったFSBLのカスタマイズを、Vitisツールを使ってやってみたいと思います。
このカスタマイズは、ZYBOのEEPROMに入っているMACアドレスを取得するためのものです。
Vitis使うのは初めてですが、どんな感じなのか。

一応Vitis参考を載せておきます。

Zynq-7000 FSBL - Xilinx Wiki - Confluence

ひでみのアイデア帳

Vitis起動

Avnet社のガイドに従うと、Vitisのデスクトップアイコンが作成されています。
これをダブルクリックでVitisを起動します。

f:id:nokixa:20211113204447p:plain:w400

eclipseベースのツールらしく、ワークスペース指定のダイアログがまず出ます。

f:id:nokixa:20211113204908p:plain:w400

最初の画面では、"Create Platform Project"を選択します。

f:id:nokixa:20211113223719p:plain:w500

プロジェクト名を入力して"Next"をクリック。

f:id:nokixa:20211113223813p:plain:w500

前にVivadoで生成したxsaファイルを指定、Operating systemはstandaloneのままで"Finish"します。

f:id:nokixa:20211113223920p:plain:w500

こんな感じの画面が出てきます。

f:id:nokixa:20211113224009p:plain:w500

FSBLの編集

Explorerウィンドウで"zynq_fsbl"を開くと、FSBLのソースコードが出てきます。このうち、"fsbl_hooks.c"を開きます。

f:id:nokixa:20211113224113p:plain:w500

前の記事で書いたように、"fsbl_hooks.c"に以下のコードを追加します。

How to obtain the MAC address of Zybo - Embedded Linux - Digilent Forum

  • 先頭にドライバヘッダのインクルードを追加
#include "xiicps.h"
#include "xemacps.h"
  • FsblHookBeforeHandoff()関数の中身を追加
/******************************************************************************
* This function is the hook which will be called  before the FSBL does a handoff
* to the application. The user can add all the customized code required to be
* executed before the handoff to this routine.
*
* @param None
*
* @return
*      - XST_SUCCESS to indicate success
*      - XST_FAILURE.to indicate failure
*
****************************************************************************/
u32 FsblHookBeforeHandoff(void)
{
    u32 Status;

    Status = XST_SUCCESS;

    /*
    * User logic to be added here.
    * Errors to be stored in the status variable and returned
    */
    fsbl_printf(DEBUG_INFO,"In FsblHookBeforeHandoff function \r\n");

    /* Read Out MAC Address */
    {
        int Status;
        XIicPs Iic;
        XIicPs_Config *Iic_Config;
        XEmacPs Emac;
        XEmacPs_Config *Mac_Config;

        unsigned char mac_addr[6];
        int i = 0;

        fsbl_printf(DEBUG_GENERAL,"Look Up I2C Configuration\n\r");
        Iic_Config = XIicPs_LookupConfig(XPAR_PS7_I2C_0_DEVICE_ID);
        if(Iic_Config == NULL) {
            return XST_FAILURE;
        }

        fsbl_printf(DEBUG_GENERAL,"I2C Initialization\n\r");
        Status = XIicPs_CfgInitialize(&Iic, Iic_Config, Iic_Config->BaseAddress);
        if(Status != XST_SUCCESS) {
            return XST_FAILURE;
        }

        fsbl_printf(DEBUG_GENERAL,"Set I2C Clock\n\r");
        XIicPs_SetSClk(&Iic, 200000);

        mac_addr[0] = 0xFA;

        fsbl_printf(DEBUG_GENERAL,"Set Memory Read Address\n\r");
        XIicPs_MasterSendPolled(&Iic, mac_addr, 1, 0x50);
        while(XIicPs_BusIsBusy(&Iic));
        fsbl_printf(DEBUG_GENERAL,"Get Mac Address\n\r");
        XIicPs_MasterRecvPolled(&Iic, mac_addr, 6, 0x50);
        while(XIicPs_BusIsBusy(&Iic));

        fsbl_printf(DEBUG_GENERAL,"MAC Addr: ");
        for(i = 0; i < 6; i++) {
            fsbl_printf(DEBUG_GENERAL,"%02x ", mac_addr[i]);
        }
        fsbl_printf(DEBUG_GENERAL,"\n\r");

        fsbl_printf(DEBUG_GENERAL,"Look Up Emac Configuration\n\r");
        Mac_Config = XEmacPs_LookupConfig(XPAR_PS7_ETHERNET_0_DEVICE_ID);
        if(Mac_Config == NULL) {
            return XST_FAILURE;
        }

        fsbl_printf(DEBUG_GENERAL,"Emac Initialization\n\r");
        Status = XEmacPs_CfgInitialize(&Emac, Mac_Config, Mac_Config->BaseAddress);
        if(Status != XST_SUCCESS){
            return XST_FAILURE;
        }

        fsbl_printf(DEBUG_GENERAL,"Set Emac MAC Address\n\r");
        Status = XEmacPs_SetMacAddress(&Emac, mac_addr, 1);
        if(Status != XST_SUCCESS){
            return XST_FAILURE;
        }

        fsbl_printf(DEBUG_GENERAL,"Verify Emac MAC Address\n\r");
        XEmacPs_GetMacAddress(&Emac, mac_addr, 1);
        if(Status != XST_SUCCESS){
            return XST_FAILURE;
        }
    }

    return (Status);
}

最後にビルドボタンを押すと、無事ビルドが完了しました。

f:id:nokixa:20211113224304p:plain:w500

Explorerウィンドウの"zynq_fsbl"の下にも"fsbl.elf"がありますし、"export" > "zybo-fsbl" > "sw" > "zybo-fsbl" > "boot"の下にもあります。

とりあえず以上

今回はここまでにしておきます。
次回はPetalinuxのほうの作業になります。

OpenCVやってみる-22. エピポーラ幾何

今回は、OpenCVチュートリアルの以下のページを参考に進めてみたいと思います。

OpenCV: Epipolar Geometry

エピポーラ幾何の理論はチュートリアルサイトの説明を参照で。

今回のテーマ画像

今回は、春のパン祭り台紙の2視点分の画像でマッチング、Epipolar lineの描画をしてみたいと思います。
似たような特徴点が複数あるので難しそうと思いましたが、RANSAC等適用すればうまくマッチングできるのではと。

import cv2
img1 = cv2.imread('harupan_210402_1.jpg')
img2 = cv2.imread('harupan_210402_2.jpg')
img1= cv2.resize(img1, None, fx=0.2, fy=0.2, interpolation=cv2.INTER_AREA)
img2= cv2.resize(img2, None, fx=0.2, fy=0.2, interpolation=cv2.INTER_AREA)

img12 = np.hstack((img1, img2))
cv2.imshow('Image', img12)
cv2.waitKey(0)

f:id:nokixa:20211016205646p:plain

画像サイズはいずれも806x605になっています。

>>> img1.shape
(806, 605, 3)
>>> img2.shape
(806, 605, 3)

特徴点検出、特徴量算出

SIFTを使いました。

sift = cv2.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)

img1_kp = cv2.drawKeypoints(img1, kp1, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
img2_kp = cv2.drawKeypoints(img2, kp2, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

img12_kp = np.hstack((img1_kp, img2_kp))
cv2.imshow('Keypoints', img12_kp)
cv2.waitKey(0)

f:id:nokixa:20211017010320p:plain

マッチング

ここでは総当たりマッチングを使います。

bf = cv2.BFMatcher()
matches = bf.match(des1, des2)
matches = sorted(matches, key = lambda x:x.distance)

img_matches = cv2.drawMatches(img1, kp1, img2, kp2, matches[:200], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv2.imshow('Matches', img_matches)
cv2.waitKey(0)

f:id:nokixa:20211016011731p:plain

いまいちな結果なので、ratio testも入れてみます。

matches_rt = bf.knnMatch(des1, des2, k=2)
good_matches = []
for m,n in matches_rt:
    if m.distance < 0.75*n.distance:
        good_matches.append(m)

good_matches = sorted(good_matches, key = lambda x:x.distance)
img_good_matches = cv2.drawMatches(img1, kp1, img2, kp2, good_matches[:200], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv2.imshow('Good matches', img_good_matches)
cv2.waitKey(0)

f:id:nokixa:20211016014617p:plain

これでもまだまだですが、この結果を使っていきます。

ちなみに、good_matchesには1169個のマッチが含まれていました。

>>> len(good_matches)
1169

Fundamental matrix計算

Fundamental matrixの計算をやってみます。
この過程でマッチング結果のinlier、outlierを判定してくれるので、 それも見てみます。

pts1 = []
pts2 = []

for i,m in enumerate(good_matches):
    pts1.append(kp1[m.queryIdx].pt)
    pts2.append(kp2[m.trainIdx].pt)

import numpy as np
pts1 = np.int32(pts1)
pts2 = np.int32(pts2)
F, mask = cv2.findFundamentalMat(pts1, pts2, cv2.FM_LMEDS)

pts1_inliers = pts1[mask.ravel() == 1]
pts2_inliers = pts2[mask.ravel() == 1]

good_matches_inliers = [m for i,m in enumerate(good_matches[:200]) if mask[i,0] == 1]

img_good_matches_inliers = cv2.drawMatches(img1,kp1,img2,kp2,good_matches_inliers[:200],None,flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv2.imshow('Good matches(inliers)', img_good_matches_inliers)
cv2.waitKey(0)

f:id:nokixa:20211017025759p:plain

しっかり合っているものだけ残っているようです。 すごい!

ちなみに、マッチング点が1169点あったのに対して、inlierは866点になっていました。

>>> len(pts1_inliers)
866

Epipolar line描画

では計算したFundamental matrixを元にEpipolar lineを描画するとどうなるかというと、

def drawlines(img1,img2,lines,pts1,pts2):
    ''' img1 - image on which we draw the epilines for the points in img2
        lines - corresponding epilines '''
    r,c,ch = img1.shape
    for r,pt1,pt2 in zip(lines,pts1,pts2):
        color = tuple(np.random.randint(0,255,3).tolist())
        x0,y0 = map(int, [0, -r[2]/r[1] ])
        x1,y1 = map(int, [c, -(r[2]+r[0]*c)/r[1] ])
        img1 = cv2.line(img1, (x0,y0), (x1,y1), color,1)
        img1 = cv2.circle(img1,tuple(pt1),5,color,-1)
        img2 = cv2.circle(img2,tuple(pt2),5,color,-1)
    return img1,img2

pts1_inliers_200 = pts1_inliers[0:200,:]
pts2_inliers_200 = pts2_inliers[0:200,:]

lines1 = cv2.computeCorrespondEpilines(pts2_inliers_200.reshape(-1,1,2),2,F)
lines1 = lines1.reshape(-1,3)
img5,img6 = drawlines(img1.copy(),img2.copy(),lines1,pts1,pts2)
lines2 = cv2.computeCorrespondEpilines(pts1_inliers_200.reshape(-1,1,2),1,F)
lines2 = lines2.reshape(-1,3)
img3,img4 = drawlines(img2.copy(),img1.copy(),lines2,pts2,pts1)
img35 = np.hstack((img3,img5))
cv2.imshow('Epipolar lines', img35)
cv2.waitKey(0)

f:id:nokixa:20211021013954p:plain

こんな感じになっちゃいました。思っていたのと違う…

試しにFundamental matrixの計算で使うマッチング点数を減らしてみたりしましたが、

F, mask = cv2.findFundamentalMat(pts1[0:200,:], pts2[0:200,:], cv2.FM_LMEDS)

pts1_inliers = pts1[mask.ravel() == 1]
pts2_inliers = pts2[mask.ravel() == 1]

pts1_inliers_200 = pts1_inliers[0:200,:]
pts2_inliers_200 = pts2_inliers[0:200,:]

lines1 = cv2.computeCorrespondEpilines(pts2_inliers_200.reshape(-1,1,2),2,F)
lines1 = lines1.reshape(-1,3)
img5,img6 = drawlines(img1.copy(),img2.copy(),lines1,pts1,pts2)
lines2 = cv2.computeCorrespondEpilines(pts1_inliers_200.reshape(-1,1,2),1,F)
lines2 = lines2.reshape(-1,3)
img3,img4 = drawlines(img2.copy(),img1.copy(),lines2,pts2,pts1)
img35 = np.hstack((img3,img5))
cv2.imshow('Epipolar lines', img35)
cv2.waitKey(0)

f:id:nokixa:20211021015009p:plain

これまた変な結果に。

チュートリアルの最後のほうをよく見てみると、特徴点が1つの平面上にあると正しくFundamental matrixを計算できないという記載がありました。

Fundamental matrixの計算について

考察してみます。
以下のサイトのpdfを参考にしています。ケンブリッジ大学出版の教科書です。

Computer Vision Models

Amazonで購入も可能なようです。

Amazon | Computer Vision: Models, Learning, and Inference | Prince, Simon J. D. | Machine Vision

Fundamental matrixについて

Fundamental matrixがどういうものかというと、途中経過は端折りますが、

任意の実空間座標\boldsymbol{w}と、2視点からの画像上でこれに対応する点\boldsymbol{x_1}, \boldsymbol{x_2} (同次座標で)について、以下の式が成り立つ

\boldsymbol{x_1} \boldsymbol{F} \boldsymbol{x_2} = 0 \tag{1}

というものです。

\boldsymbol{x_1} = \lbrack x_1 y_1 1 \rbrack ^T , \boldsymbol{x_2} = \lbrack x_2 y_2 1 \rbrack ^T , \boldsymbol{F} = \begin{bmatrix} f_{11} & f_{12} & f_{13} \\
f_{21} & f_{22} & f_{23} \\
f_{31} & f_{32} & f_{33} \end{bmatrix}

というように要素を書き下すと、式(1)は

x_2 x_1 f_{11} + x_2 y_1 f_{12} + x_2 f_{13} + y_2 x_1 f_{21} + y_2 y_1 f_{f22} + y_2 f_{23} + x_1 f_{31} + y_1 f_{32} + f_{33} = 0 \tag{2} \lbrack x_2 x_1 \: x_2 y_1 \: x_2 \: y_2 x_1 \: y_2 y_1 \: y_2 \: x_1 \: y_1 \: 1 \rbrack \boldsymbol{f} = 0 \tag{3} (\boldsymbol{f} = \lbrack f_{11} \: f_{12} \: f_{13} \: f_{21} \: f_{22} \: f_{23} \: f_{31} \: f_{32} \: f_{33} \rbrack ^T)

と書けます。
\boldsymbol{F}はスケールの任意性があるので、自由度が8となっていて、8個以上のマッチングペアがあれば一意に決まります。

ここで、マッチングペアの点に対する実空間座標が全て同じ平面上にあった場合を考えます。

実空間座標を\boldsymbol{w}=\lbrack u \; v \; w \rbrack ^T とすると、画像上の点(同次座標)\boldsymbol{x_1}, \boldsymbol{x_2}u, v, wを使って以下のように表されます。

\lambda_1 \boldsymbol{x_1} = \boldsymbol{\Omega_1} \boldsymbol{w} + \boldsymbol{\tau_1}
\lambda_2 \boldsymbol{x_2} = \boldsymbol{\Omega_2} \boldsymbol{w} + \boldsymbol{\tau_2}

要素ごとに書くと、

\lambda_1 x_1 = \Omega_{1_{11}} u + \Omega_{1_{12}} v + \Omega_{1_{13}} w + \tau_{1_1}
\lambda_1 y_1 = \Omega_{1_{21}} u + \Omega_{1_{22}} v + \Omega_{1_{23}} w + \tau_{1_2}
\lambda_1 = \Omega_{1_{31}} u + \Omega_{1_{32}} v + \Omega_{1_{33}} w + \tau_{1_3}
\lambda_2 x_2 = \Omega_{2_{11}} u + \Omega_{2_{12}} v + \Omega_{2_{13}} w + \tau_{2_1}
\lambda_2 y_2 = \Omega_{2_{21}} u + \Omega_{2_{22}} v + \Omega_{2_{23}} w + \tau_{2_2}
\lambda_2 = \Omega_{2_{31}} u + \Omega_{2_{32}} v + \Omega_{2_{33}} w + \tau_{2_3}

式(2)に\lambda_1 \lambda_2を掛けると、全ての項が\lambda_1 x_1, \lambda_2 x_2, \lambda_1, \lambda_2の積で表されるので、上の6式を代入してみると、式(2)における係数がいずれも u, v, w, uv, uw, vw, u^2, v^2, w^2, 1 の線型結合で表されることがわかります。 なので、式(3)について8個の線形独立な係数ベクトルを用意することができ、\boldsymbol{f}を一意に(定数倍の自由度を除いて)決めることができます。

ただし、u, v, wの間に相関がある、例えばすべての実空間座標が1つの平面上にあると、 係数ベクトルがより少ない要素の線形結合になり、8個の線形独立なものを用意できなくなります。そうすると、一意に\boldsymbol{f}を定めることができなくなると。

なんとなくうまくまとまらないけどそんな感じ。

ここまで

今回の内容はここまでにします。
本当はちゃんとFundamental matrixが求められれば3次元座標の推定もできるのですが…

参考

tex書き方参考。特にはてなブログでの書き方が特殊だったので。

はてなブログでTex記法を使って行列を書く時の注意点 - 医療職からデータサイエンティストへ

hatena blogでtexによる下付き文字がうまく表示されない - MEMOcho-

LaTeXコマンド - 空白 - 水平方向のスペース - quad, hspace

ZYBOを進める - 26. ツールバージョン変更(2020.2)

前回の続きです。
前回はVivadoプロジェクトでのビットストリーム生成まで行いました。今回はこれをPetalinuxプロジェクトに取り込みます。

Petalinuxツールでの手順

Petalinuxプロジェクトの作成

まずはPetalinuxプロジェクトの作成。

入力:

petalinux-create --type project --template zynq --name Zybo-base-linux-peta

実行結果:

noki@noki-VirtualBox:~/work/petalinux$ petalinux-create --type project --template zynq --name Zybo-base-linux-peta 
INFO: Create project: Zybo-base-linux-peta
INFO: New project successfully created in /home/noki/work/petalinux/Zybo-base-linux-peta
noki@noki-VirtualBox:~/work/petalinux$


ハードウェアコンフィグレーションの取り込み

Petalinux(ver 2020.2)のユーザガイド(UG1144)を見ると、今までと違ってxsaファイルを指定するように変わっています。
xsaファイルは、Vivadoから以下のように生成できます。

  • File > Export > Export Hardware... をクリック
  • ウィザード最初はとりあえず Nextをクリック
  • Output では include bitstreamを選択
  • XSAファイル名とエクスポート先を指定、Finishをクリック

f:id:nokixa:20211009022246p:plain:w300

f:id:nokixa:20211009022501p:plain:w300

f:id:nokixa:20211009022723p:plain:w300

f:id:nokixa:20211012072620j:plain:w300

次にPetalinuxの操作です。 petalinux-configコマンドで、ハードウェア情報としてxsaファイルを指定します。

petalinux-config --get-hw-description ../../zybo/Zybo-base-linux/proj/Zybo-base-linux.xsa

実行結果:

noki@noki-VirtualBox:~/work/petalinux/Zybo-base-linux-peta$ petalinux-config --get-hw-description ../../zybo/Zybo-base-linux/proj/Zybo-base-linux.xsa  
INFO: Sourcing build tools
INFO: Getting hardware description...
INFO: Rename Zybo-base-linux.xsa to system.xsa
[INFO] Generating Kconfig for project
[INFO] Menuconfig project
configuration written to /home/noki/work/petalinux/Zybo-base-linux-peta/project-spec/configs/config

*** End of the configuration.
*** Execute 'make' to start the build or try 'make help'.

[INFO] Extracting yocto SDK to components/yocto
[INFO] Sourcing build environment
[INFO] Generating kconfig for Rootfs
[INFO] Silentconfig rootfs
[INFO] Generating plnxtool conf
[INFO] Adding user layers
[INFO] Generating workspace directory
noki@noki-VirtualBox:~/work/petalinux/Zybo-base-linux-peta$ 


Linuxイメージのビルド

Petalinuxのビルドのコマンドを走らせるだけです。

入力:

petalinux-build 

実行結果:

noki@noki-VirtualBox:~/work/petalinux/Zybo-base-linux-peta$ petalinux-build 
INFO: Sourcing build tools
[INFO] Building project
[INFO] Sourcing build environment
[INFO] Generating workspace directory
INFO: bitbake petalinux-image-minimal
Parsing recipes: 100% |##########################################| Time: 0:07:51
Parsing of 2995 .bb files complete (0 cached, 2995 parsed). 4265 targets, 204 skipped, 0 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
NOTE: Fetching uninative binary shim from file:///home/noki/work/petalinux/Zybo-base-linux-peta/components/yocto/downloads/uninative/9498d8bba047499999a7310ac2576d0796461184965351a56f6d32c888a1f216/x86_64-nativesdk-libc.tar.xz;sha256sum=9498d8bba047499999a7310ac2576d0796461184965351a56f6d32c888a1f216
Initialising tasks: 100% |#######################################| Time: 0:00:08
Checking sstate mirror object availability: 100% |###############| Time: 0:00:30
Sstate summary: Wanted 976 Found 801 Missed 175 Current 0 (82% match, 0% complete)
NOTE: Executing Tasks
NOTE: Setscene tasks completed
NOTE: Tasks Summary: Attempted 3513 tasks of which 2615 didn't need to be rerun and all succeeded.
INFO: Successfully copied built images to tftp dir: /tftpboot
[INFO] Successfully built project
noki@noki-VirtualBox:~/work/petalinux/Zybo-base-linux-peta$ 

今回は40分ぐらいで完了しました。


ブートイメージの作成

起動用のBOOT.BINを作ります。FPGAのビットストリームも含まれます。
Petalinuxプロジェクトのimages/linuxディレクトリ下にsystem.bitというのがありましたが、Vivadoプロジェクトで生成されたビットストリーム(system_wrapper.bit)と比較すると全く同じでした。このsystem.bitを使うことにします。

入力:

petalinux-package --boot --fsbl images/linux/zynq_fsbl.elf --fpga images/linux/system.bit --u-boot

実行結果:

noki@noki-VirtualBox:~/work/petalinux/Zybo-base-linux-peta$ petalinux-package --boot --fsbl images/linux/zynq_fsbl.elf --fpga images/linux/system.bit --u-boot
INFO: Sourcing build tools
INFO: File in BOOT BIN: "/home/noki/work/petalinux/Zybo-base-linux-peta/images/linux/zynq_fsbl.elf"
INFO: File in BOOT BIN: "/home/noki/work/petalinux/Zybo-base-linux-peta/images/linux/system.bit"
INFO: File in BOOT BIN: "/home/noki/work/petalinux/Zybo-base-linux-peta/images/linux/u-boot.elf"
INFO: File in BOOT BIN: "/home/noki/work/petalinux/Zybo-base-linux-peta/images/linux/system.dtb"
INFO: Generating Zynq binary package BOOT.BIN...


****** Xilinx Bootgen v2020.2
  **** Build date : Nov 15 2020-06:11:24
    ** Copyright 1986-2020 Xilinx, Inc. All Rights Reserved.


[INFO]   : Bootimage generated successfully

INFO: Binary is ready.
noki@noki-VirtualBox:~/work/petalinux/Zybo-base-linux-peta$

images/linuxディレクトリを覗いてみます。

noki@noki-VirtualBox:~/work/petalinux/Zybo-base-linux-peta$ ll images/linux/
total 82372
drwxrwxr-x 3 noki noki     4096 10月 11 22:07 ./
drwxrwxr-x 3 noki noki     4096 10月  1 01:18 ../
-rw-rw-r-- 1 noki noki  2957068 10月 11 22:07 BOOT.BIN
-rw-r--r-- 1 noki noki     2010 10月  1 01:18 boot.scr
-rw-r--r-- 1 noki noki 11554268 10月  1 01:39 image.ub
drwxr-xr-x 2 noki noki     4096 10月  1 01:18 pxelinux.cfg/
-rw-r--r-- 1 noki noki 13964800 10月  1 01:39 rootfs.cpio
-rw-r--r-- 1 noki noki  7200308 10月  1 01:39 rootfs.cpio.gz
-rw-r--r-- 1 noki noki  7200372 10月  1 01:39 rootfs.cpio.gz.u-boot
-rw-r--r-- 1 noki noki  8650752 10月  1 01:39 rootfs.jffs2
-rw-r--r-- 1 noki noki     6784 10月  1 01:39 rootfs.manifest
-rw-r--r-- 1 noki noki  7236872 10月  1 01:39 rootfs.tar.gz
-rw-r--r-- 1 noki noki  2083850 10月  1 00:46 system.bit
-rw-r--r-- 1 noki noki    25867 10月  1 01:22 system.dtb
-rw-r--r-- 1 noki noki   743119 10月  1 01:24 u-boot.bin
-rw-r--r-- 1 noki noki   809080 10月  1 01:24 u-boot.elf
-rw-r--r-- 1 noki noki  4326040 10月  1 01:39 uImage
-rw-r--r-- 1 noki noki 12671032 10月  1 01:39 vmlinux
-rw-r--r-- 1 noki noki  4325976 10月  1 01:39 zImage
-rw-r--r-- 1 noki noki   552296 10月  1 01:21 zynq_fsbl.elf
noki@noki-VirtualBox:~/work/petalinux/Zybo-base-linux-peta$ 


Linuxイメージの実機起動

microSDカードを用意して、images/linuxディレクトリにある

  • BOOT.BIN
  • boot.scr
  • image.ub

をコピーします。
boot.scrはPetalinux 2017.4でやったときには存在しませんでした。
なお、PC自体にSDカードスロットはありますが、VirtualBoxから扱うのが面倒そうなので、USB接続のカードリーダを使用しました。

VirtualBox(ホスト=Mac、ゲスト=Windows 10)でSDカードを認識させる方法 - give IT a try

カードリーダはELECOM社製のものです。
VirtualBoxメニューで、デバイス > USB > Generic USB Storageと選択すると、仮想マシンUbuntuからSDカードにアクセスできました。

f:id:nokixa:20211012012311p:plain

noki@noki-VirtualBox:~$ ls /dev/sd*
/dev/sda  /dev/sda1  /dev/sdb  /dev/sdb1  /dev/sdb2
noki@noki-VirtualBox:~$ 

抜き差しして試してみると、/dev/sdbがSDカードに当たるようでした。

SDカードに上記ファイルをコピー、ZYBOに差し込んで、PCとZYBOをUSBケーブルで接続、PCでTeratermを起動、ZYBOで電源投入すると、ちゃんとLinux起動が確認できました。

シリアルコンソールに出力された起動ログを全部掲載してみます。
最後のほうでユーザ名、パスワードを入力してログインしています。

U-Boot 2020.01 (Sep 30 2021 - 16:22:50 +0000)

CPU:   Zynq 7z010
Silicon: v3.1
DRAM:  ECC disabled 512 MiB
Flash: 0 Bytes
NAND:  0 MiB
MMC:   mmc@e0100000: 0
Loading Environment from SPI Flash... SF: Detected s25fl128s with page size 256 Bytes, erase size 64 KiB, total 16 MiB
*** Warning - bad CRC, using default environment

In:    serial@e0001000
Out:   serial@e0001000
Err:   serial@e0001000
Net:
ZYNQ GEM: e000b000, mdio bus e000b000, phyaddr -1, interface rgmii-id

Warning: ethernet@e000b000 using MAC address from DT
eth0: ethernet@e000b000
Hit any key to stop autoboot:  0
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
Found U-Boot script /boot.scr
2010 bytes read in 15 ms (130.9 KiB/s)
## Executing script at 03000000
11554268 bytes read in 650 ms (17 MiB/s)
## Loading kernel from FIT Image at 10000000 ...
   Using 'conf@system-top.dtb' configuration
   Verifying Hash Integrity ... OK
   Trying 'kernel@1' kernel subimage
     Description:  Linux kernel
     Type:         Kernel Image
     Compression:  uncompressed
     Data Start:   0x100000f8
     Data Size:    4325976 Bytes = 4.1 MiB
     Architecture: ARM
     OS:           Linux
     Load Address: 0x00200000
     Entry Point:  0x00200000
     Hash algo:    sha256
     Hash value:   eee70692c31f7b4758702d73c0abc4366b6e9af4b6ccad4298214c93a1fc2b1f
   Verifying Hash Integrity ... sha256+ OK
## Loading ramdisk from FIT Image at 10000000 ...
   Using 'conf@system-top.dtb' configuration
   Verifying Hash Integrity ... OK
   Trying 'ramdisk@1' ramdisk subimage
     Description:  petalinux-image-minimal
     Type:         RAMDisk Image
     Compression:  uncompressed
     Data Start:   0x10426a34
     Data Size:    7200308 Bytes = 6.9 MiB
     Architecture: ARM
     OS:           Linux
     Load Address: unavailable
     Entry Point:  unavailable
     Hash algo:    sha256
     Hash value:   f9c831ec9998ae4ac1ab2a714a3c155cf27d0337528795c188f66d1b98002d65
   Verifying Hash Integrity ... sha256+ OK
## Loading fdt from FIT Image at 10000000 ...
   Using 'conf@system-top.dtb' configuration
   Verifying Hash Integrity ... OK
   Trying 'fdt@system-top.dtb' fdt subimage
     Description:  Flattened Device Tree blob
     Type:         Flat Device Tree
     Compression:  uncompressed
     Data Start:   0x1042045c
     Data Size:    25867 Bytes = 25.3 KiB
     Architecture: ARM
     Hash algo:    sha256
     Hash value:   89e73a92946f87241fbdb15e974fd2d913c8477282aa60df32038686f32d6e84
   Verifying Hash Integrity ... sha256+ OK
   Booting using the fdt blob at 0x1042045c
   Loading Kernel Image
   Loading Ramdisk to 1e428000, end 1eb05e34 ... OK
   Loading Device Tree to 1e41e000, end 1e42750a ... OK

Starting kernel ...

Booting Linux on physical CPU 0x0
Linux version 5.4.0-xilinx-v2020.2 (oe-user@oe-host) (gcc version 9.2.0 (GCC)) #1 SMP PREEMPT Thu Sep 30 16:22:50 UTC 2021
CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=18c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
OF: fdt: Machine model: xlnx,zynq-7000
earlycon: cdns0 at MMIO 0xe0001000 (options '115200n8')
printk: bootconsole [cdns0] enabled
Memory policy: Data cache writealloc
cma: Reserved 16 MiB at 0x1f000000
percpu: Embedded 15 pages/cpu s31948 r8192 d21300 u61440
Built 1 zonelists, mobility grouping on.  Total pages: 129920
Kernel command line: console=ttyPS0,115200 earlycon root=/dev/ram0 rw
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes, linear)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes, linear)
mem auto-init: stack:off, heap alloc:off, heap free:off
Memory: 484516K/524288K available (6144K kernel code, 217K rwdata, 1844K rodata, 1024K init, 131K bss, 23388K reserved, 16384K cma-reserved, 0K highmem)
rcu: Preemptible hierarchical RCU implementation.
rcu:    RCU restricting CPUs from NR_CPUS=4 to nr_cpu_ids=2.
        Tasks RCU enabled.
rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies.
rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=2
NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
efuse mapped to (ptrval)
slcr mapped to (ptrval)
L2C: platform modifies aux control register: 0x72360000 -> 0x72760000
L2C: DT/platform modifies aux control register: 0x72360000 -> 0x72760000
L2C-310 erratum 769419 enabled
L2C-310 enabling early BRESP for Cortex-A9
L2C-310 full line of zeros enabled for Cortex-A9
L2C-310 ID prefetch enabled, offset 1 lines
L2C-310 dynamic clock gating enabled, standby mode enabled
L2C-310 cache controller enabled, 8 ways, 512 kB
L2C-310: CACHE_ID 0x410000c8, AUX_CTRL 0x76760001
random: get_random_bytes called from start_kernel+0x260/0x440 with crng_init=0
zynq_clock_init: clkc starts at (ptrval)
Zynq clock init
sched_clock: 64 bits at 325MHz, resolution 3ns, wraps every 4398046511103ns
clocksource: arm_global_timer: mask: 0xffffffffffffffff max_cycles: 0x4af477f6aa, max_idle_ns: 440795207830 ns
Switching to timer-based delay loop, resolution 3ns
Console: colour dummy device 80x30
Calibrating delay loop (skipped), value calculated using timer frequency.. 650.00 BogoMIPS (lpj=3250000)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
CPU: Testing write buffer coherency: ok
CPU0: Spectre v2: using BPIALL workaround
CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
Setting up static identity map for 0x100000 - 0x100060
rcu: Hierarchical SRCU implementation.
smp: Bringing up secondary CPUs ...
CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
CPU1: Spectre v2: using BPIALL workaround
smp: Brought up 1 node, 2 CPUs
SMP: Total of 2 processors activated (1300.00 BogoMIPS).
CPU: All CPU(s) started in SVC mode.
devtmpfs: initialized
VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 4
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
futex hash table entries: 512 (order: 3, 32768 bytes, linear)
pinctrl core: initialized pinctrl subsystem
NET: Registered protocol family 16
DMA: preallocated 256 KiB pool for atomic coherent allocations
cpuidle: using governor menu
hw-breakpoint: found 5 (+1 reserved) breakpoint and 1 watchpoint registers.
hw-breakpoint: maximum watchpoint size is 4 bytes.
zynq-ocm f800c000.ocmc: ZYNQ OCM pool: 256 KiB @ 0x(ptrval)
e0001000.serial: ttyPS0 at MMIO 0xe0001000 (irq = 26, base_baud = 6250000) is a xuartps
printk: console [ttyPS0] enabled
printk: console [ttyPS0] enabled
printk: bootconsole [cdns0] disabled
printk: bootconsole [cdns0] disabled
vgaarb: loaded
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
mc: Linux media interface: v0.10
videodev: Linux video capture interface: v2.00
pps_core: LinuxPPS API ver. 1 registered
pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
PTP clock support registered
EDAC MC: Ver: 3.0.0
FPGA manager framework
Advanced Linux Sound Architecture Driver Initialized.
clocksource: Switched to clocksource arm_global_timer
thermal_sys: Registered thermal governor 'step_wise'
NET: Registered protocol family 2
tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 6144 bytes, linear)
TCP established hash table entries: 4096 (order: 2, 16384 bytes, linear)
TCP bind hash table entries: 4096 (order: 3, 32768 bytes, linear)
TCP: Hash tables configured (established 4096 bind 4096)
UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
UDP-Lite hash table entries: 256 (order: 1, 8192 bytes, linear)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
PCI: CLS 0 bytes, default 64
Trying to unpack rootfs image as initramfs...
Freeing initrd memory: 7032K
hw perfevents: no interrupt-affinity property for /pmu@f8891000, guessing.
hw perfevents: enabled with armv7_cortex_a9 PMU driver, 7 counters available
workingset: timestamp_bits=14 max_order=17 bucket_order=3
jffs2: version 2.2. (NAND) (SUMMARY)  c 2001-2006 Red Hat, Inc.
io scheduler mq-deadline registered
io scheduler kyber registered
zynq-pinctrl 700.pinctrl: zynq pinctrl initialized
XGpio: gpio@41230000: registered, base is 1023
GPIO IRQ not connected
XGpio: gpio@41200000: registered, base is 1019
XGpio: gpio@41220000: registered, base is 1015
XGpio: gpio@41220000: dual channel registered, base is 1011
dma-pl330 f8003000.dmac: Loaded driver for PL330 DMAC-241330
dma-pl330 f8003000.dmac:        DBUFF-128x8bytes Num_Chans-8 Num_Peri-4 Num_Events-16
xilinx-vdma 43000000.dma: Xilinx AXI VDMA Engine Driver Probed!!
brd: module loaded
loop: module loaded
spi_master spi0: cannot find modalias for /amba/spi@e000d000/flash@0
spi_master spi0: Failed to create SPI device for /amba/spi@e000d000/flash@0
libphy: Fixed MDIO Bus: probed
CAN device driver interface
libphy: MACB_mii_bus: probed
RTL8211E Gigabit Ethernet e000b000.ethernet-ffffffff:00: attached PHY driver [RTL8211E Gigabit Ethernet] (mii_bus:phy_addr=e000b000.ethernet-ffffffff:00, irq=POLL)
macb e000b000.ethernet eth0: Cadence GEM rev 0x00020118 at 0xe000b000 irq 28 (00:0a:35:00:1e:53)
e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ehci-pci: EHCI PCI platform driver
usbcore: registered new interface driver usb-storage
i2c /dev entries driver
cdns-i2c e0004000.i2c: 400 kHz mmio e0004000 irq 22
cdns-i2c e0005000.i2c: 400 kHz mmio e0005000 irq 23
xilinx-vtc 43c00000.v_tc: device found, version 6.020
cdns-wdt f8005000.watchdog: Xilinx Watchdog Timer with timeout 10s
EDAC MC: ECC not enabled
Xilinx Zynq CpuIdle Driver started
sdhci: Secure Digital Host Controller Interface driver
sdhci: Copyright(c) Pierre Ossman
sdhci-pltfm: SDHCI platform and OF driver helper
mmc0: SDHCI controller on e0100000.mmc [e0100000.mmc] using ADMA
ledtrig-cpu: registered to indicate activity on CPUs
clocksource: ttc_clocksource: mask: 0xffff max_cycles: 0xffff, max_idle_ns: 551318127 ns
timer #0 at (ptrval), irq=41
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
fpga_manager fpga0: Xilinx Zynq FPGA Manager registered
NET: Registered protocol family 10
Segment Routing with IPv6
sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
NET: Registered protocol family 17
can: controller area network core (rev 20170425 abi 9)
NET: Registered protocol family 29
can: raw protocol (rev 20170425)
can: broadcast manager protocol (rev 20170425 t)
can: netlink gateway (rev 20190810) max_hops=1
Registering SWP/SWPB emulation handler
of-fpga-region fpga-full: FPGA Region probed
hctosys: unable to open rtc device (rtc0)
of_cfs_init
mmc0: new high speed SDHC card at address 59b4
of_cfs_init: OK
ALSA device list:
  No soundcards found.
Freeing unused kernel memory: 1024K
mmcblk0: mmc0:59b4 NCard 7.36 GiB
Run /init as init process
INIT:  mmcblk0: p1 p2
version 2.88 booting
Starting udev
udevd[74]: starting version 3.2.8
random: udevd: uninitialized urandom read (16 bytes read)
random: udevd: uninitialized urandom read (16 bytes read)
random: udevd: uninitialized urandom read (16 bytes read)
udevd[75]: starting eudev-3.2.8
random: fast init done
FAT-fs (mmcblk0p1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.
hwclock: can't open '/dev/misc/rtc': No such file or directory
Thu Sep 30 16:39:32 UTC 2021
hwclock: can't open '/dev/misc/rtc': No such file or directory
urandom_read: 2 callbacks suppressed
random: dd: uninitialized urandom read (512 bytes read)
Configuring packages on first boot....
 (This may take several minutes. Please do not power off the machine.)
Running postinst /etc/rpm-postinsts/100-sysvinit-inittab...
update-rc.d: /etc/init.d/run-postinsts exists during rc.d purge (continuing)
 Removing any system startup links for run-postinsts ...
  /etc/rcS.d/S99run-postinsts
INIT: Entering runlevel: 5
Configuring network interfaces... udhcpc: started, v1.31.0
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: no lease, forking to background
done.
Starting haveged: haveged: listening socket at 3
haveged: haveged starting up


Starting Dropbear SSH server: random: dropbearkey: uninitialized urandom read (32 bytes read)
random: dropbearkey: uninitialized urandom read (32 bytes read)

haveged: haveged: ver: 1.9.5; arch: generic; vend: ; build: (gcc 9.2.0 CTV); collect: 128K

haveged: haveged: cpu: (VC); data: 16K (D); inst: 16K (D); idx: 12/40; sz: 15006/57790

haveged: haveged: tot tests(BA8): A:1/1 B:1/1 continuous tests(B):  last entropy estimate 7.99919

haveged: haveged: fills: 0, generated: 0

random: crng init done
Public key portion is:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYauJlnpZlSMdVB09VYHIapW/xJICPWVLS4hd8MfzGCF5K0u1OLkcizlug//SJJj+WM8/2rIcN/u2csFKZjXQjg47evhpialK6ZkTgxkBETaQpYZZ6vWtI7havTl/fpyzb1v933SKGyjjLnoD1PWQB2si9uTzsV1IR3uWKFuXIhLsYw4fI2awkpPI5pdG3fnZcmU6+IBqQTuPwJFRek2DrEJ5HjeWlqG78Hb8dR/bsgC9wRZW0zCBx1Rbtf6w6t4Y39Tx1UgCpaF612JWjuT6/xqNgB9UgbAvHbEt+GwxJbiUmOJhTG6IbyoR8hxLmWexvaM6cx0mcbz6IY31wRiR9 root@Zybo-base-linux-peta
Fingerprint: sha1!! 8d:89:2a:e7:6b:92:14:31:f4:e5:db:0a:04:6c:64:ec:08:92:c8:45
dropbear.
hwclock: can't open '/dev/misc/rtc': No such file or directory
Starting internet superserver: inetd.
Starting syslogd/klogd: done
Starting tcf-agent: OK

PetaLinux 2020.2 Zybo-base-linux-peta /dev/ttyPS0

Zybo-base-linux-peta login: root
Password:
root@Zybo-base-linux-peta:~# ls /
bin    dev    home   lib    mnt    root   sbin   tmp    var
boot   etc    init   media  proc   run    sys    usr
root@Zybo-base-linux-peta:~#

ここまで

今回はここまでにしておきます。
次回はPetalinuxの設定等、今までやった通りに変更していきたいと思います。
Vitisを使ってのFSBLのカスタマイズもやりたい。

ZYBOを進める - 25. ツールバージョン変更(2020.2)

久しぶりにZYBOのほうを進めたいと思います。

内容

前回(既に1年前…)までは

  • VMWare + Ubuntu18.04
  • Vivado 2017.4
  • Petalinux 2017.4

の環境を使っていました。

ただ、今回はXilinxツールのVitisも使っていきたいと思っていて、使用するツールバージョンを新しくしたいと思います。

ツールバージョン変更作業

仮想マシン環境作り直し

最近Avnet社のUltra96ボードもいじろうとしています。
こちらでは以下のサイトにリファレンスデザインやガイドがありますが、こちらのガイドに従うと、VirtualBoxを使う流れになります。ZYBO開発のほうでもVirtualBoxを使うほうに切り替えていきたいと思います。

Ultra96-V2 | element14 | Avnet Boards Community

「Reference Designs」のタブを開いて、「Development Using Ubuntu Desktop Linux」のところを見ると「VirtualBox and Linux VM installation Guide」というのがいくつかあります。
これに従うと、

  • VirtualBoxのインストール、Ubuntu OSのセットアップ
  • VivadoおよびVitisのインストール
  • Petalinuxのインストール
  • その他必要な環境の整備

を行うことができます。

f:id:nokixa:20211009003207p:plain:w300

環境を用意したら、digilentのVivado向けのボード定義ファイルを、Vivadoインストールパスの下に置きます。

Installing Vivado, Xilinx SDK, and Digilent Board Files - Digilent Reference

こちらのサイトから、「Master Branch ZIP Archive」をクリックしてzipファイルをダウンロード、解凍します。解凍されたファイルを、以下のようにコピーします。

コピー元: vivado-boards-master/new/board_files/ コピー先: /tools/Xilinx/Vivado/2020.2/data/boards/board_files/

f:id:nokixa:20210926025147p:plain

f:id:nokixa:20210926010136p:plain


Vivadoプロジェクト移行

今までで作ったVivadoプロジェクトも、新しいVivadoに移行します。
とりあえず今まで使っていたZybo-base_linuxプロジェクトを仮想マシンにコピー。.xprファイルをVivadoで開きます。
すると、まずプロジェクトのバージョン違いの警告が出てきます。

f:id:nokixa:20210926013425p:plain

「Automatically upgrade to the current version」にチェックを入れた状態でOKし、プロジェクトのアップグレードを試みます。

アップグレードの必要なIPがあるようです。

f:id:nokixa:20210926015239p:plain

OKをクリックして、Vivadoのメニューで「Reports」 > 「Report IP Status」と開くと、IPのアップグレード必要性の状況が表示されます。
ここからアップグレードを行うこともできます。

f:id:nokixa:20210926015314p:plain

IPアップグレードを行うと、Critical Warningが発生しました。

f:id:nokixa:20211009012710p:plain

ip_upgrade.logを見てみると、Critical Warningを出しているIPが記載されています。

1つ目はsystem_v_tc_out_0 (ブロックデザイン内、Video Timing Controller)。

Upgrade Log for IP 'system_v_tc_out_0'

1. Summary
----------

CAUTION (success, with warnings) in the upgrade of system_v_tc_out_0 from xilinx.com:ip:v_tc:6.1 (Rev. 12) to xilinx.com:ip:v_tc:6.2 (Rev. 1)

After upgrade, an IP may have parameter and port differences compared to the original customization. Please review the parameters within the IP customization GUI to ensure proper functionality. Also, please review the updated IP instantiation template to ensure proper connectivity, and update your design if required.

2. Connection Warnings
----------------------

Detected external port differences while upgrading 'system_v_tc_out_0'. These changes may impact your design.


-Upgrade has added port 'sof_state'


3. Customization warnings
-------------------------

An attempt to modify the value of disabled parameter 'GEN_F0_VSYNC_HSTART' from '640' to '1280' has been ignored for IP 'system_v_tc_out_0'

An attempt to modify the value of disabled parameter 'GEN_F0_VSYNC_HEND' from '695' to '1280' has been ignored for IP 'system_v_tc_out_0'

An attempt to modify the value of disabled parameter 'GEN_F0_VBLANK_HSTART' from '640' to '1280' has been ignored for IP 'system_v_tc_out_0'

An attempt to modify the value of disabled parameter 'GEN_F0_VBLANK_HEND' from '640' to '1280' has been ignored for IP 'system_v_tc_out_0'

An attempt to modify the value of disabled parameter 'GEN_F1_VSYNC_HSTART' from '695' to '1280' has been ignored for IP 'system_v_tc_out_0'

An attempt to modify the value of disabled parameter 'GEN_F1_VSYNC_HEND' from '695' to '1280' has been ignored for IP 'system_v_tc_out_0'

An attempt to modify the value of disabled parameter 'GEN_F1_VBLANK_HSTART' from '640' to '1280' has been ignored for IP 'system_v_tc_out_0'

An attempt to modify the value of disabled parameter 'GEN_F1_VBLANK_HEND' from '640' to '1280' has been ignored for IP 'system_v_tc_out_0'

ディスエーブルされているパラメータの設定は無視される、ということが書かれています。
ブロックデザインでIPのカスタマイズGUIを出してみると、

f:id:nokixa:20210928003113p:plain

となっています。
Video Formatが現状では720pになっていて他のパラメータがグレーアウトされていますが、 これをCustomに変えてみると、各パラメータ変更できました。
特にここのパラメータも気にしないでよさそうかなと。

後はsof_stateというポートも追加されたようです。
Video Timing Controller IPのガイドを見ると、これはAXI4 Video Out bridgeと一緒に使用するときにbridgeのsof_stateポートを接続してください、ということが書かれています。

f:id:nokixa:20210928033038p:plain

2つ目はsystem_v_axi4s_vid_out_0_0 (ブロックデザイン内、AXI4-Stream to Video Out)。

Upgrade Log for IP 'system_v_axi4s_vid_out_0_0'

1. Summary
----------

CAUTION (success, with warnings) in the upgrade of system_v_axi4s_vid_out_0_0 (xilinx.com:ip:v_axi4s_vid_out:4.0) from (Rev. 8) to (Rev. 11)

After upgrade, an IP may have parameter and port differences compared to the original customization. Please review the parameters within the IP customization GUI to ensure proper functionality. Also, please review the updated IP instantiation template to ensure proper connectivity, and update your design if required.

2. Connection Warnings
----------------------

Detected external port differences while upgrading 'system_v_axi4s_vid_out_0_0'. These changes may impact your design.


-Upgrade has added port 'fifo_read_level'

-Upgrade has added port 'sof_state_out'

fifo_read_levelとsof_state_outというポートが追加になったようです。
sof_state_outは先ほどのVideo Timing Controllerに接続する信号のようなので、ブロックデザイン上で接続します。fifo_read_levelは何のための信号かよく分からず。IPのガイドを見ても何も記載がありませんでした。特に何もしないでいいかな。

f:id:nokixa:20210928034900p:plain

最後はsystem_axi_gpio_led_0 (ブロックデザイン内、AXI GPIO)。
gpio_io_i、gpio_io_tポートが消えています。他にもAXI GPIOのインスタンスは存在しますが、このインスタンスだけ出力専用モードに設定されているためかと思われます。元々使われていないポートなので、特に対応は不要かと。

Upgrade Log for IP 'system_axi_gpio_led_0'

1. Summary
----------

CAUTION (success, with warnings) in the upgrade of system_axi_gpio_led_0 (xilinx.com:ip:axi_gpio:2.0) from (Rev. 17) to (Rev. 24)

After upgrade, an IP may have parameter and port differences compared to the original customization. Please review the parameters within the IP customization GUI to ensure proper functionality. Also, please review the updated IP instantiation template to ensure proper connectivity, and update your design if required.

2. Connection Warnings
----------------------

Detected external port differences while upgrading 'system_axi_gpio_led_0'. These changes may impact your design.


-Upgrade has removed port 'gpio_io_i'

-Upgrade has removed port 'gpio_io_t'

というところで、ブロックデザインを一部変更したので、Validate Designをして保存、ビットストリーム生成をします。
ブロックデザイン内のIP全部再合成になるので時間がかかります…

一部要変更点。

  • ブロックデザインの外部ポートが一部変わった(axi_gpio_led_0のポートが一部なくなった)ので、ラッパの再生成も必要でした。
    • Vivadoプロジェクトのデフォルトの言語をVerilogに変更していたので、ラッパはsystem_wrapper.vが使用される。
  • 外部ポート名が一部変更になっているので、制約ファイル(ZYBO_Master.xdc)で変更
    leds_4bits_tri_io → leds_4bits_tri_o
  • ほかにも制約ファイルで変更したIOポート名があった気がしますが、メモ忘れました…

f:id:nokixa:20210928230915p:plain


一旦ここまで

長くなったのでここまでにします。
VivadoプロジェクトはGitHubに上げたいですが、現状のプロジェクト管理方法だといまいちなので、また後で直して上げたい…