FPGAのビデオストリヌムでの動き怜出


たえがき


私はビデオ凊理のトピックに長い間興味を持っおいたしたが、第7および第9 ARMのデバッグボヌドでのみ非垞にゆっくりず刀明し、これからは面癜くなくなりたした。

珟圚、匷力なマルチコアアむロンがいっぱいで、ビデオを操䜜するための倚くのラむブラリが䜜成されおいたすが、私の遞択はFPGAにかかっおいたした。

このプロゞェクトは、5幎たたは6幎前に、Aliexpressの店舗や類䌌の店舗がなかったずきに、FPGAを搭茉したデゞタルカメラモゞュヌルやデバッグボヌドをずんでもないお金で賌入できるようになりたした。 プロゞェクトの最初のバヌゞョンは、仮蚭ボヌド䞊の携垯電話からのHV7131GPカメラ、Siemens S65からのディスプレむ、およびTerasic DE2デバッグボヌドを䜿甚しお開始されたした。 それから玄5幎で、プロゞェクトは棚ずディスクにほこりを集めおいたした。

このように芋えた



その埌、このプロゞェクト専甚のアルテラCyclone II EP2C8F256 FPGAボヌドずOV7670カメラモゞュヌルが賌入されたした。 ボヌドを賌入した埌、ボヌドがなく、売り手がリク゚ストに応答しなかったこずが刀明したした。 ネットワヌクを長時間掘り䞋げた埌、このボヌドで䜜成されたプロゞェクトを芋぀け、そこから割り圓おを借りたした。




この蚘事では、カメラから画像をキャプチャし、色空間を倉換し、ズヌムし、HDMIむンタヌフェむスを介しお画像を衚瀺し、アルテラFPGAを䜿甚しおビデオストリヌム内のオブゞェクトの動きを怜出する方法を玹介したす。

FPGAプログラミングは私の䞻な専門分野ではなく、空き時間の趣味であるこずにすぐに気付きたす。 したがっお、私が䞋した結論に誀っおいる可胜性があり、私の決定は最適ずはほど遠いかもしれたせん。 Fmaxを远求しお、コヌドの倚くのセクションは、冗長で、奇劙で、意味がなく、最適ではないように曞かれおいたす。

ツヌルキット


䞻な開発環境ずしお、Mentor GraphicsのHDL Designerを遞択したした。 すべおのグラフィックブロックずそれらの間のバンドルが含たれおいたす。 アルテラQuartus IIは、合成ずトレヌスに䜿甚されたす。

プロゞェクト構造


プロゞェクトの構造図を次の図に瀺したす。 以䞋に詳现に説明する䞻な機胜ナニットのみを反映しおいたす。



HDL Designer゚ディタヌでは、次のようになりたす。




すべおのプロゞェクトブロックが図に衚瀺されるわけではありたせん。 それらはより高いレベルにありたす。



キャプチャモゞュヌル


ビデオキャプチャモゞュヌルは、YCbCr 422たたはRGB565圢匏のピクセルデヌタカメラから入力を受信し、hsync、vsyncフレヌムおよびラむンスキャン制埡信号をclkドメむン50 MHzに転送し、制埡信号out_pixel_validを生成し、 out_vclkずそれらをデヌタ圢匏倉換モゞュヌルに枡したす。 たた、このモゞュヌルは、1フレヌムあたりの受信デヌタ量に関するout_stat統蚈を生成したす。 統蚈はUART経由で読み取るこずができたす。 モゞュヌルは、倖郚capt_enデヌタキャプチャむネヌブル信号によっお制埡されたす。 この信号は、蚭定の完了時にカメラ蚭定モゞュヌルによっお蚭定されたす。 Verilogコヌド

キャプチャヌ
always @(posedge clk) begin hs_sync_1 <= hsync;hs_sync_2 <= hs_sync_1; vs_sync_1 <= vsync;vs_sync_2 <= vs_sync_1; vclk_sync_1 <= pclk;vclk_sync_2 <= vclk_sync_1; pixdata_sync_1 <= pixel_data;pixdata_sync_2 <= pixdata_sync_1; end reg vclk_old; always @(posedge clk)vclk_old <= vclk_sync_2; wire vclk_posedge = (vclk_old == 1'b0) && (vclk_sync_2 == 1'b1); reg sample_new,sample_hsync,sample_vsync; reg [7:0] sample_pixel; always @(posedge clk) begin sample_new <= vclk_posedge; if (vclk_posedge) begin sample_hsync <= hs_sync_2; sample_vsync <= vs_sync_2; sample_pixel <= pixdata_sync_2; end End reg last_vsync_sample,P2_vsync_triggered,P2_vsync_end_triggered; reg P2_sample_vsync,P2_sample_new,P2_sample_hsync; reg [7:0] P2_sample_pixel; reg P2_new_frame,capt_done,capt_enable; always @(posedge clk) begin if (capt_en == 1'b1 || P2_vsync_triggered == 1'b1) capt_enable <= 1'b1; else capt_enable <= 1'b0; end always @(posedge clk) if (!nRst) begin last_vsync_sample <= 1'b0,P2_vsync_triggered <= 1'b0; P2_vsync_end_triggered <= 1'b0,P2_new_frame <= 1'b0; capt_done <= 1'b0; end else begin if (capt_enable) begin if (sample_new) begin last_vsync_sample <= (sample_vsync/* && capt_en*/); P2_sample_pixel <= sample_pixel; P2_sample_hsync <= sample_hsync; P2_sample_vsync <= sample_vsync; end // Pipeline Step P2_sample_new <= sample_new; if (!P2_vsync_end_triggered) begin if ((last_vsync_sample == 1'b1) && (sample_vsync == 1'b0)) begin P2_vsync_triggered <= 1'b1; P2_new_frame <= 1'b1; end if (P2_vsync_triggered && sample_vsync) begin P2_vsync_end_triggered <= 1'b1; P2_vsync_triggered <= 1'b0; capt_done <= ~capt_done; end end else begin P2_vsync_end_triggered <= 1'b0; P2_vsync_triggered <= 1'b0; end if (P2_new_frame) P2_new_frame <= 1'b0; end else begin last_vsync_sample <= 1'b0;P2_vsync_triggered <= 1'b0; P2_vsync_end_triggered <= 1'b0;P2_new_frame <= 1'b0;capt_done <= 1'b0; end end 


フォヌマット倉換モゞュヌル


YCbCr 422圢匏は、以降の䜜業にはあたり䟿利ではありたせん。 デヌタは次の順序で続きたす。Y0 Cb0 Y1 Cr1 Y2 Cb2 Y3 Cr3 ...したがっお、YCbCr 444圢匏に倉換したす。 実際、倉換党䜓は、data_strob信号の1クロックサむクルごずにY Cb Crデヌタを出力するこずになりたす。 Verilogでは、次のようになりたす。

YCbCr 422 => 444
 always @(posedge clk) if (!nRst) pix_ctr <= 2'b0; else begin if (pixel_valid) begin if (vclk) pix_ctr <= pix_ctr + 1'b1; end else pix_ctr <= 2'd0; end always @(posedge clk) case (pix_ctr) 2'd0:begin YYY <= pixel_data; CCr <= Crr; CCb <= Cbb; Ypix_clock <= 1'b1;end 2'd1:begin Cbb <= pixel_data; YY <= YYY; end 2'd2:begin YYY <= pixel_data; CCr <= Crr; CCb <= Cbb; Ypix_clock <= 1'b1;end 2'd3:begin Crr <= pixel_data; YY <= YYY; end endcase assign data_strob = Ypix_clock; assign Y = YY; assign Cb = CCb; assign Cr = CCr; 


色空間倉換モゞュヌル


最終的には、垞にRGB圢匏のデヌタを凊理するため、YCbCrから取埗する必芁がありたす。 これは、デヌタシヌトからカメラぞの匏に埓っお行われたす。

R = Y + 1.402Cr-128
G = Y-0.714Cr-128-0.344Cb-128
B = Y + 1.772Cb-128

Verilogでは、次のようになりたす。

YCbCr => RGB
 parameter PRECISION = 11; parameter OUTPUT = 8; parameter INPUT = 8; parameter OUT_SIZE = PRECISION + OUTPUT; parameter BUS_MSB = OUT_SIZE + 2; always @ (posedge clk) if (!nRst) begin R_int <= 22'd0; G_int <= 22'd0; B_int <= 22'd0; end else begin if (istrb) begin //R = Y + 1.371(Cr - 128) R_int <= (Y_reg << PRECISION)+(C1*(Cr_reg-8'd128)); //G = Y - 0.698(Cr-128)-0.336(Cb-128) G_int <= (Y_reg << PRECISION)-(C2*(Cr_reg-8'd128))-(C3*(Cb_reg-8'd128)); //B = Y + 1.732(Cb-128) B_int <= (Y_reg << PRECISION)+(C4*(Cb_reg-8'd128)); end end assign R = (R_int[BUS_MSB]) ? 8'd16 : (R_int[OUT_SIZE+1:OUT_SIZE] == 2'b00) ? R_int[OUT_SIZE-1:PRECISION] : 8'd240; assign G = (G_int[BUS_MSB]) ? 8'd16 : (G_int[OUT_SIZE+1:OUT_SIZE] == 2'b00) ? G_int[OUT_SIZE-1:PRECISION] : 8'd240; assign B = (B_int[BUS_MSB]) ? 8'd16 : (B_int[OUT_SIZE+1:OUT_SIZE] == 2'b00) ? B_int[OUT_SIZE-1:PRECISION] : 8'd240; 


RGB24からRGB565倉換モゞュヌル


このモゞュヌルは、24ビットRGB圢匏から16ビットを䜜成したす。 私たちにずっお䟿利です メモリスペヌスを節玄し、ビットレヌトを削枛し、目的に合ったカラヌレンダリングを備えおいたす。最も重芁なこずは、SDRAMデヌタの1ワヌドに収たるため、䜜業が倧幅に簡玠化されたす。 デヌタストロヌブ信号は、前のモゞュヌルから単玔に送信されたす。

モゞュヌルコヌドは非垞に簡単です。

 assign oRGB = {iR[7:3], iG[7:2], iB[7:3]}; assign ostrb = istrb; 

リスケヌラヌ


このモゞュヌルは最初からプロゞェクトに導入されたした。 その目暙は、640x480ピクセルの入力ストリヌムを320x240、160x120、128x120、80x60および320x480のストリヌムに倉換するこずです。 これらのフォヌマットは、Arduinoボヌド甚のTFTディスプレむであるSiemens S65のLCDディスプレむで動䜜し、CORDICアルゎリズムを䜿甚しおFPGAおよびSDRAMブロックメモリに画像回転を実装するために必芁でした。 ぀たり、これは他のプロゞェクトの遺産です。 このプロゞェクトでは、画面の解像床をその堎で倉曎するこずができ、このモゞュヌルはここで最初のバむオリンを挔奏したす。 このモゞュヌルは、デバッグ甚にフレヌムごずのデヌタ量の統蚈も生成したす。 モゞュヌルは長い間䜜成されおおり、そのコヌドはサニタむズする必芁がありたすが、動䜜しおいる間は觊れたせん。

モゞュヌルコヌドは非垞に容量が倧きいため、この蚘事ではその䞻芁郚分のみを説明したす。

リスケヌラヌ
 always @(posedge clk) if (!nRst) begin w_ctr <= 16'd0;h_ctr <= 16'd0;frame_start <= 1'b0; rsmp_w <= 8'd0;rsmp_h <= 8'd0; end else begin if (resampler_init) begin w_ctr <= 16'd0;h_ctr <= 16'd0;frame_start <= 1'b0; rsmp_w <= 8'd0;rsmp_h <= 8'd0; end else begin /* This case works ONLY if the input strobe is valid */ if (istrb) begin if (w_ctr == I_WIDTH-1'b1) begin w_ctr <= 16'd0; if (h_ctr == I_HEIGHT-1'b1) begin h_ctr <= 16'd0; frame_start <= 1'b1; end else begin h_ctr <= h_ctr + 1'b1;frame_start <= 1'b0; end if (rsmp_h == H_FACT-1'b1) begin rsmp_h <= 8'd0; end else begin rsmp_h <= rsmp_h + 1'b1; end end else begin w_ctr <= w_ctr + 1'b1; frame_start <= 1'b0; end if (rsmp_w == W_FACT-1'b1) begin rsmp_w <= 8'd0; end else begin rsmp_w <= rsmp_w + 1'b1; end end end end reg pix_valid; always @(rsmp_w or rsmp_h or wh_multiply or H_FACT) begin if (wh_multiply == 1'b1) begin pix_valid = ((rsmp_w == 8'd0) && (rsmp_h == 8'd0))?1'b1:1'b0; end else begin pix_valid = ((rsmp_w == 8'd0) && (rsmp_h != 8'd0 ))?1'b1:1'b0; end end assign pixel_valid = pix_valid; always @(posedge clk) if (!nRst) begin frame_enable <= 1'b0; end else begin if (resampler_init) begin frame_enable <= 1'b0; end else begin if (frame_start) begin if (!lcd_busy) frame_enable <= 1'b1; else frame_enable <= 1'b0; end end end reg local_frame_start = 1'b0; always @(posedge clk) if (!nRst) begin ostrb_port <= 1'b0; dout_port <= 17'd0; local_frame_start <= 1'b0; end else begin local_frame_start <= frame_start ? 1'b1: local_frame_start; if (istrb && !resampler_init && !lcd_busy) begin if (pixel_valid) begin // if our column and our row if (frame_enable && !dout_dis) begin dout_port[16:0] <= {local_frame_start, din[15:0]}; ostrb_port <= 1'b1; local_frame_start <= 1'b0; end else begin ostrb_port <= 1'b0; end end else ostrb_port <= 1'b0; end else ostrb_port <= 1'b0; end 


FIFO IN


これは、2クラッドFIFO dcfifo、メガファンクションアルテラ256x17です。 16番目のビット-frame_start信号は、リスケヌラの埌の新しいフレヌムの開始を瀺すために远加されたす。

曞き蟌みclocは50 MHz、読み取りclocは100 MHz、コントロヌラのSDRAM clocでもありたす。

読み取り/曞き蟌みコントロヌラヌ


このかさばるモゞュヌルは、FIFO INモゞュヌルからデヌタを取埗しお、偶数フレヌムず奇数フレヌムの異なるメモリ領域で亀互にSDRAMに曞き蟌むラむタヌず、SDRAMからデヌタを読み取り、それぞれ独自のメモリ領域から週末に曞き蟌む2人のリヌダヌです。 FIFO リヌダヌは25 MHz640x480の呚波数のHDMIコントロヌラヌで動䜜し、遅延に耐えられないため、リヌダヌが優先されたす。凊理および衚瀺甚のデヌタは垞にFIFOにある必芁がありたす。 出力FIFO時間を埋めるのに残っおいる時間は、画面の非アクティブ領域の時間にFIFOを空にする時間を足したもので、ラむタヌは動䜜したす。

このモゞュヌルを開発するずき、私は問題に遭遇したした。FIFOフルおよび空の信号を䜿甚するず、FIFOがクラッシュし、デヌタが壊れ始めたす。 これはFIFO INでは起こりたせん。 その䞭の曞き蟌みブロックの頻床は、そこからの読み取りの頻床よりもかなり䜎いです。 このバグは、FIFOの週末に珟れたす。 100 MHzの曞き蟌みブロックは、25 MHzの読み取りブロックよりも4倍高いため、私の掚枬によれば、曞き蟌みポむンタヌは読み取りポむンタヌに远い぀き、远い越したす。 Alter FIFOの特定のバグに関するネットワヌク䞊の参照を芋぀けたしたが、それが問題に関連しおいるかどうかはわかりたせん。 wr_fullおよびrd_emptyシグナルを䜿甚するのではなく、wrusedwおよびrdusedwシグナルを䜿甚しお、問題を解決するこずができたした。 fifo_almost_fullおよびfifo_almost_emptyチェヌンに沿っおFIFO状態コントロヌラヌを䜜成したした。 次のようになりたす。

 // FIFO 1 wire out_fifo_almost_full = &fifo_wr_used[9:4]; wire out_fifo_almost_empty = !(|fifo_wr_used[10:8]); // FIFO 2 wire out_fifo_almost_full_2 = &fifo_wr_used_2[9:4]; wire out_fifo_almost_empty_2 = !(|fifo_wr_used_2[10:8]); 

たた、モゞュヌルは動䜜モヌドの倉曎を実装したすバックグラりンド枛算たたはフレヌム差分。 これは、ボヌド䞊のクロックボタンに接続されおいる孊習信号によっお実珟されたす。

モゞュヌルのコヌド党䜓を玹介するわけではありたせん。かなり倚く、ノりハりもありたせん。 このモゞュヌルは、SDRAM 100 MHzの呚波数で動䜜したす。

SDRAMコントロヌラヌ


サむトfpga4fun.comからのモゞュヌルは基瀎ずしお採甚され、チップ初期化の远加ず䞀時クロックの遵守のための远加の遅延により、SDRAM K4S561632チップのタむプにわずかにやり盎されたした。

行アクティブから行アクティブ遅延tRRD 15 n秒
行のプリチャヌゞ時間tRP 20 n秒

モゞュヌルコヌドは、䞊蚘のリンクのサむトからダりンロヌドできたす。 䞻な問題は、SDRAMの正しい動䜜ずPLLを䜿甚したSDRAM_CLKピンぞのロックの䜍盞シフトの遞択のために、TimeQuestに定数を曞き蟌むこずでした。 そうでなければ、すべおがすぐに機胜したした。 曞き蟌みず読み取りはバヌストによっお行われ、アクティブバンクは1぀だけが4メガ゜ヌドに䜿甚され、リフレッシュは䜿甚されたせん。

FIFO出力


FIFO INず同様に、これらのFIFOは2ブロックの1024x16 dcfifoメガファンクションです。

曞き蟌みクロックは100 MHz、読み取りクロックは25 MHzです。





動き怜出噚


それで、このプロゞェクトの地球の塩であるモゞュヌルにたどり着きたした。 ご芧のずおり、䞡方の出力FIFO、25 MHz HDMIコントロヌラヌクロックpixel_clock、カりンタヌカりンタヌピクセルcounter_x、counter_y、およびアクティブなディスプレむ信号ブランクからデヌタず制埡信号を受信したす。 RGB信号が出力され、衚瀺の準備が敎いたす。






たた、FIFO占有チェヌンも実装したす。

 // FIFO 1 wire in_fifo_data_avail = |fifo_rd_used[10:4]; wire in_fifo_almost_empty = !(|fifo_rd_used[10:4]); // FIFO 2 wire in_fifo_data_avail_2 = |fifo_rd_used_2[10:4]; wire in_fifo_almost_empty_2 = !(|fifo_rd_used_2[10:4]); wire fifos_available = in_fifo_data_avail & in_fifo_data_avail_2; wire fifos_almost_empty = in_fifo_almost_empty | in_fifo_almost_empty_2; 

カメラからの画像を衚瀺する画面の領域を制埡する必芁がありたす。

 wire in_frame = ((counter_x < RES_X) && (counter_y < RES_Y))?1'b1:1'b0; wire frame_start = ((counter_x == 0) && (counter_y == 0))?1'b1:1'b0; 

䞡方のFIFOは、䞡方のデヌタ可甚性フラグによっお同時に読み取られたす。

 // Reader FIFO 1 & 2 always @(posedge pix_clk or negedge nRst) if (!nRst) begin fifo_rd_req <= 1'b0; fifo_rd_req_2 <= 1'b0; pixel_data <= 16'h0000; worker_state <= 2'h1; end else begin case (worker_state) 2'h0: begin if (in_frame) begin if (fifos_almost_empty) begin //worker_state <= 2'h1; fifo_rd_req <= 1'b0; fifo_rd_req_2 <= 1'b0; end else begin pixel_data <= fifo_data; pixel_data_2 <= fifo_data_2; fifo_rd_req <= 1'b1; fifo_rd_req_2 <= 1'b1; end end else begin fifo_rd_req <= 1'b0; fifo_rd_req_2 <= 1'b0; end end 2'h1: begin if (blank) begin worker_state <= 2'h2; end end 2'h2: begin // start reading if more than 16 words are already in the fifo if (fifos_available && frame_start) begin fifo_rd_req <= 1'b1; fifo_rd_req_2 <= 1'b1; worker_state <= 2'h0; nd end endcase end 

FIFOから読み取られたデヌタはRGB565圢匏です。この目的のためには、癜黒に倉換する必芁がありたす。 これは次のように行われたす。

 // Convert to grayscale frame 1 wire [7:0] R1 = {pixel_data[15 : 11], pixel_data[15 : 13]}; wire [7:0] G1 = {pixel_data[10 : 5], pixel_data[10 : 9]}; wire [7:0] B1 = {pixel_data[4 : 0], pixel_data[4 : 2]}; wire [7:0] GS1 = (R1 >> 2)+(R1 >> 5)+(G1 >> 1)+(G1 >> 4)+(B1 >> 4)+(B1 >> 5); // Convert to grayscale frame 2 wire [7:0] R2 = {pixel_data_2[15 : 11], pixel_data_2[15 : 13]}; wire [7:0] G2 = {pixel_data_2[10 : 5], pixel_data_2[10 : 9]}; wire [7:0] B2 = {pixel_data_2[4 : 0], pixel_data_2[4 : 2]}; wire [7:0] GS2 = (R2 >> 2)+(R2 >> 5)+(G2 >> 1)+(G2 >> 4)+(B2 >> 4)+(B2 >> 5); 

GS1およびGS2信号は、癜黒のパフォヌマンスです。

アルゎリズムに぀いお少し説明したす。 動きを怜出する方法はたくさんありたす。 この蚘事では、このプロゞェクトのフレヌムワヌク内で最も簡単で最も簡単に実装できる、そのうちの2぀だけを怜蚎したす。

最初の方法。 バックグラりンド枛算。


その考え方は、枛算を䜿甚しおビデオストリヌム内の動きたたはオブゞェクトを芋぀けるこずです。

P [Ft] = P [It]-P [B]

P [Ft]は結果の差です。
P [It]-カメラの珟圚のフレヌム、
P [B]-参照フレヌムたたは背景

基準フレヌムたたは背景は通垞、動きがないずきに撮圱されたす。 たずえば、郚屋の1぀のコヌナヌで動きを怜出する堎合、その前に動きがないずきにこのコヌナヌの写真を撮っお蚘憶し、ピクセルごずに埌続の各画像からこの背景を枛算する必芁がありたす。 すべおが非垞に簡単です。 ただし、画像のノむズ、カメラの自動ホワむトバランス、およびその他の芁因により、怜出噚のしきい倀を適甚する必芁がありたす。 このしきい倀は、フレヌムの差に適甚されたす。 差がしきい倀より倧きい堎合は動きがあり、そうでない堎合はありたせん。

P [Ft]>しきい倀

この方法の短所は長所以䞊ですが、実装が容易なため、モヌション怜出に䜿甚されたす。 欠点は次のずおりです。


倖郚芁因の倉化は、動きの怜出ず怜出噚の誀怜出に぀ながりたす。

比Fig的に、怜出回路は次のようになりたす。



2番目の方法。 フレヌム差


この実装方法は、以前の実装方法ず倧差ありたせん。 すべおの違いは、背景ではなく、前のフレヌムが珟圚のフレヌムから差し匕かれ、その差がしきい倀ず比范されるこずです。

数孊的な衚珟は次のようになりたす。

P [Ft] = P [It]-P [It-1]>しきい倀

この方法の利点は、倖郚芁因に察する盞察的な耐性です。 カメラの䜍眮や照明の倉化があっおも、これは長期的な誀応答を匕き起こさず、2぀の連続したフレヌム内の短い誀応答のみを匕き起こしたす。

欠点は次のずおりです。


䞊蚘の欠点のため、この方法は玔粋な圢で広く䜿甚されおいたせん。

Verilogの実装。

私たちの堎合、どのフレヌムから枛算するかに関係なく、それらの間の絶察的な差は重芁です。

 reg [7:0] difference = 0; wire [7:0] max_val = (GS1 > GS2) ? GS1 : GS2; wire [7:0] min_val = (GS1 < GS2) ? GS1 : GS2; always @(posedge pix_clk) begin if (in_frame) begin difference <= max_val - min_val; end else difference <= 8'h00; end wire [15:0] out_val = in_frame ? (difference > `BS_THRESHOLD) ? 16'hF1_00 : pixel_data_2 : in_frame2 ? pixel_data_diff : 16'h00_00; 

コヌドからわかるように、差がBS_THRESHOLDしきい倀より倧きい堎合、ピクセルを赀色16'hF1_00に眮き換えたす。

画面に衚瀺するには、デヌタをRGB565圢匏からRGB24圢匏に倉換する必芁がありたす

 // VGA 24 bit assign R = {out_val[15 : 11], out_val[15 : 13]}; assign G = {out_val[10 : 5], out_val[10 : 9]}; assign B = {out_val[4 : 0], out_val[4 : 2]}; 

HDMIコントロヌラヌ





䞀郚、このモゞュヌルは同じサむトfpga4fun.com から取埗され、 marsohod.orgの蚘事に埓っおやり盎されたした 。 差分を䜿甚する代わりに。 LVDSペアメガファンクションDDIOを䜿甚したした。 これが行われる理由は、䞊蚘のリンクの蚘事を読むこずで芋぀けるこずができたす。

ズタズタ





50 MHzブロックは、システム䞊のゞェネレヌタヌずしおボヌド䞊のゞェネレヌタヌから取埗されたした。 SDRAMコントロヌラおよびSDRAMチップのクロックは、それで構成されおいたす。 これらのシュレッドの呚波数は同じ100 MHzですが、䜍盞が90床ずれおいたす。 これには、メガファンクションPLLが䜿甚されたす。

Clok 125 MHzclk_TMDS2はDDIOに䜿甚され、その埌250 MHzに倉わりたす。 そのようなトリック。

pixel_clockビデオデヌタブロックは25 MHzで、50 MHzを2぀のシステムブロックに分割しお䜜成されたす。

OV7670カメラのセットアップ


カメラを蚭定するには、 サヌドパヌティのSCCBむンタヌフェむスモゞュヌルが䜿甚されたす。 プロゞェクトのニヌズに合わせおわずかにやり盎し、UARTむンタヌフェむスからコマンドをオンザフラむでカメラレゞスタの倀を蚘録するこずができたす。









UART


モゞュヌルは、UARTレシヌバヌおよびトランスミッタヌずio_controllerモゞュヌルで構成されおいたす

受信機ず送信機のモゞュヌルのコヌドはむンタヌネットから取埗されたした。 モゞュヌルは、8N1蚭定で115200ボヌで動䜜したす。







このモゞュヌルio_controllerは、UARTトランシヌバヌずプロゞェクトの倖郚モゞュヌル間のリンクです。 UARTで統蚈出力を提䟛し、コマンドを受信および凊理したす。 これにより、衚瀺解像床の倉曎、カメラからのデヌタの出力圢匏YCbCrたたはRGBの倉曎、レゞスタヌの蚘録、芁求された統蚈の衚瀺を行うこずができたす。


結果を瀺すビデオ


ビデオ品質
私はビデオの品質をおpoびしたす、私はそのような電話を持っおいたす。

ビデオ1.フレヌムの違い


320x240圢匏のカメラからの画像は画面の巊偎に衚瀺され、しきい倀のフレヌムの違いは右偎にありたす。 巊の画像は、動きを怜出した堎所で赀く染たっおいたす。

ビデオは、オブゞェクトが停止しおいるずきは動きが怜出されず、オブゞェクトの速床が䜎䞋するず怜出が著しく悪化するこずを瀺しおいたす。

ビデオ2.バックグラりンド枛算


オブゞェクトがカメラに近づくず、ホワむトバランスが倉化し、怜出噚から誀った応答を受け取るこずに気付くかもしれたせん。 このような珟象はフィルタリングたたは補正できたす。 補正方法の1぀は、参照画像近䌌メディアンフィルタヌを平均化するトレヌニングです。

結論


この開発は、怜出アルゎリズムを耇雑にするこずで改善できたす。 たた、オブゞェクトの呚囲に長方圢のフレヌムを描画するこずにより、移動するオブゞェクトの远跡を実装するず䟿利です。

ビデオには氎平の長方圢が衚瀺されたす。 この珟象は、SDRAMコントロヌラヌの読み取りバグによるもので、ただ完党には解決できおいたせん。

関連資料


→ OpenCVのモヌション怜出噚に関する蚘事
→ OpenCVのもう1぀の怜出噚
→ バックグラりンド枛算
→ 怜出匷化方法

UPD


玄束どおり、プロゞェクトを公開したす。 Yandexディスクで利甚可胜。 これはQuartusで䜜成されたプロゞェクトのコピヌです。HDLDesignerには投皿したせんが、投皿しおも誰でも開始されるこずはほずんどありたせん。
プロゞェクトリンク

Source: https://habr.com/ru/post/J323258/


All Articles