FPGA实现画人脸框

一、既然用两帧连续的肤色图像,则需要对图像延迟一拍,以此来得到人脸图像的开始标志和介素标志。

//==========================================================================
//==    帧开始标志pos_vsync和帧结束标志neg_vsync
//==========================================================================
always @(posedge clk) begin
    face_vsync_r <= face_vsync;
end

assign pos_vsync =  face_vsync && ~face_vsync_r;
assign neg_vsync = ~face_vsync &&  face_vsync_r;

 二、利用行场计数器,得到人脸图像的横纵坐标。

//==========================================================================
//==    帧差图像的行场计数器
//==========================================================================
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        face_x <= 10'd0;
    else if(add_face_x) begin
        if(end_face_x)
            face_x <= 10'd0;
        else
            face_x <= face_x + 10'd1;
    end
end

assign add_face_x = face_de;
assign end_face_x = add_face_x && face_x== COL-10'd1;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        face_y <= 10'd0;
    else if(add_face_y) begin
        if(end_face_y)
            face_y <= 10'd0;
        else
            face_y <= face_y + 10'd1;
    end
end

assign add_face_y = end_face_x;
assign end_face_y = add_face_y && face_y== ROW-10'd1;

三、 根据上面所得的人脸图像的横纵坐标,从而可确定出框的四个顶点坐标。

//==========================================================================
//==    帧运行:人脸框选
//==========================================================================
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        x_min <= COL;
    end
    else if(pos_vsync) begin
        x_min <= COL;
    end
    else if(face_data==16'hffff && x_min > face_x && face_de) begin
        x_min <= face_x;
    end
end
//---------------------------------------------------
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        x_max <= 0;
    end
    else if(pos_vsync) begin
        x_max <= 0;
    end
    else if(face_data==16'hffff && x_max < face_x && face_de) begin
        x_max <= face_x;
    end
end
//---------------------------------------------------
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        y_min <= ROW;
    end
    else if(pos_vsync) begin
        y_min <= ROW;
    end
    else if(face_data==16'hffff && y_min > face_y && face_de) begin
        y_min <= face_y;
    end
end
//---------------------------------------------------
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        y_max <= 0;
    end
    else if(pos_vsync) begin
        y_max <= 0;
    end
    else if(face_data==16'hffff && y_max < face_y && face_de) begin
        y_max <= face_y;
    end
end

四、保存上面所得的四个顶点坐标值(利用前一帧到当前帧的间隙来保存坐标值,从而供当前帧来实时使用)。 

//==========================================================================
//==    帧结束:保存坐标值
//==========================================================================
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        x_min_r <= 0;
        x_max_r <= 0;
        y_min_r <= 0;
        y_max_r <= 0;
    end
    else if(neg_vsync) begin
        x_min_r <= x_min;
        x_max_r <= x_max;
        y_min_r <= y_min;
        y_max_r <= y_max;
    end
end

至此,便得到了人脸框啦。 

五、原图的行场计数器

//==========================================================================
//==    原图的行场计数器
//==========================================================================
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        RGB_x <= 10'd0;
    else if(add_RGB_x) begin
        if(end_RGB_x)
            RGB_x <= 10'd0;
        else
            RGB_x <= RGB_x + 10'd1;
    end
end

assign add_RGB_x = face_de;
assign end_RGB_x = add_RGB_x && RGB_x== COL-10'd1;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        RGB_y <= 10'd0;
    else if(add_RGB_y) begin
        if(end_RGB_y)
            RGB_y <= 10'd0;
        else
            RGB_y <= RGB_y + 10'd1;
    end
end

assign add_RGB_y = end_RGB_x;
assign end_RGB_y = add_RGB_y && RGB_y== ROW-10'd1;

六、人脸框和原图输出
用按键来控制识别效果,一种是原图的人脸检测,一种是二值化中值滤波、膨胀腐蚀后的人脸检测效果。

//==========================================================================
//==    最终数据输出:包围盒+图像
//==========================================================================
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
		key_num <= 1'b0;
	else if(key_vld)
		key_num <= ~key_num;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
		TFT_de	  <= 1'b0;
		TFT_hsync <= 1'b0;
		TFT_vsync <= 1'b0;
		TFT_data  <= 16'b0;
	end
	else if(key_num==1'b0) begin //按键按下的时候得到白色方框和原图
		if((RGB_y >= y_min_r-1 && RGB_y <= y_min_r+1) && RGB_x >= x_min_r && RGB_x <= x_max_r) begin
			TFT_data <= 16'b11111_000000_00000;
		end
		else if((RGB_y >= y_max_r-1 && RGB_y <= y_max_r+1) && RGB_x >= x_min_r && RGB_x <= x_max_r) begin
			TFT_data <= 16'b11111_000000_00000;
		end
		else if((RGB_x >= x_min_r-1 && RGB_x <= x_min_r+1) && RGB_y >= y_min_r && RGB_y <= y_max_r) begin
			TFT_data <= 16'b11111_000000_00000;
		end
		else if((RGB_x >= x_max_r-1 && RGB_x <= x_max_r+1) && RGB_y >= y_min_r && RGB_y <= y_max_r) begin
			TFT_data <= 16'b11111_000000_00000;
		end
		else begin
			TFT_de    <= RGB_de;
			TFT_hsync <= RGB_hsync;
			TFT_vsync <= RGB_vsync;
			TFT_data  <= RGB_data;
		end
	end
    else if(key_num==1'b1) begin //按键释放的时候得到白色方框和二值化腐蚀膨胀后的图像数据
		if((face_y >= y_min_r-1 && face_y <= y_min_r+1) && face_x >= x_min_r && face_x <= x_max_r) begin
			TFT_data <= 16'b11111_000000_00000;
		end
		else if((face_y >= y_max_r-1 && face_y <= y_max_r+1) && face_x >= x_min_r && face_x <= x_max_r) begin
			TFT_data <= 16'b11111_000000_00000;
		end
		else if((face_x >= x_min_r-1 && face_x <= x_min_r+1) && face_y >= y_min_r && face_y <= y_max_r) begin
			TFT_data <= 16'b11111_000000_00000;
		end
		else if((face_x >= x_max_r-1 && face_x <= x_max_r+1) && face_y >= y_min_r && face_y <= y_max_r) begin
			TFT_data <= 16'b11111_000000_00000;
		end
		else begin
			TFT_de    <= face_de;
			TFT_hsync <= face_hsync;
			TFT_vsync <= face_vsync;
			TFT_data  <= face_data;
		end
    end
end

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值