当前位置:网站首页>Construction of Hisilicon 3559 universal platform: rotation operation on the captured YUV image
Construction of Hisilicon 3559 universal platform: rotation operation on the captured YUV image
2022-07-02 23:00:00 【Run! The bug is coming】
Preface
In order to further consolidate yvu How to store the format and deal with more application scenarios , In addition YUV How to rotate the image
Conventional algorithm
Generally speaking , The angle to rotate is nothing more than 90,180,270, As long as we can switch to 90 Flipping or mirroring after degrees can achieve other angles , Refer to the figure below , The first line becomes Y13Y9Y5Y1, Corresponding V4U4 Also mentioned above , But it's obvious how much computation is needed or how much is it from another angle
void rotateYUV420SP(unsigned char src[],unsigned char des[],int width,int height)
{
int wh = width * height;
int k = 0;
for(int i=0;i<width;i++)
{
// rotate Y
for(int j=0;j<height;j++)
{
des[k] = src[width*j + i];
k++;
}
}
for(int i=0;i<width;i+=2)
{
// rotate vu
for(int j=0;j<height/2;j++)
{
des[k] = src[wh+ width*j + i];
des[k+1]=src[wh + width*j + i+1];
k+=2;
}
}
}
HI_MPI_VPSS_SetChnRotation
Haisi naturally considered this , I have hardware acceleration at the bottom , It is convenient to provide the corresponding rotation function HI_MPI_VPSS_SetChnRotation And any angle HI_MPI_VPSS_SetChnRotationEx, Just provide vpss Of group,chnl And rotation angle , It's very convenient to use , stay vpss After initialization, it is called
s32Ret = HI_MPI_VPSS_SetChnRotation(VpssGrp, VpssChn[1], ROTATION_90);
if(s32Ret != HI_SUCCESS)
{
printf("HI_MPI_VPSS_SetChnRotation failed with %#x\n", s32Ret);
return HI_FAILURE;
}
matters needing attention
It should be noted that when saving the output, you must not forget to modify the resolution of the coding channel ! Otherwise, there will be an error that the image cannot be obtained ! Just because dump Problems with routines , Directly in vpss Saved after yuv, Only y The weight is correct ,uv horrible . Fortunately, I woke up at the boss's point , The thought of venc It doesn't fit this part at all !( Similarly, there is the next record YUV422 Code can not get the problem )
passageway AUTO Not supported in mode .
Support only semi-planar 420 And single component pixel format .
( The following two notices are in the manual , Careful, it's easy to find )
Complementary algorithm
Reference blog
https://blog.csdn.net/huangjiazhi_/article/details/103960883
// Yuv420pRotate.cpp : Defines the entry point for the console application .
//
#include "stdafx.h"
// clockwise Clockwise
// contrarotate Counter clockwise rotation
// flip horizontal Mirror reversal / Flip horizontal
/** * Clockwise rotation 90. * Take the element : Start from the first point at the bottom left , From bottom to top , Take points from left to right ; * Put the elements : Start from the first position on the top left , From left to right , From the top down ; Convert each column into each row . * * @param yuvFileaName One frame YUV420P File format * @param width The width of the image * @param height The height of the image * * @return empty */
void clockwiseRotate90(const char* yuvFileaName, int width, int height){
FILE* fp = NULL;
fopen_s(&fp, yuvFileaName, "rb");
unsigned char* yuvbuf = new unsigned char[width*height * 3 / 2];
fread(yuvbuf, width*height * 3 / 2, 1, fp);
fclose(fp);
int idx = 0;
//Y
unsigned char* dstbuf = new unsigned char[width*height * 3 / 2];
for (int i = 0; i <= width - 1; i++){
for (int j = height - 1; j >= 0; j--){
dstbuf[idx++] = *(yuvbuf + (j*width + i));
}
}
//U
unsigned char* uheader = yuvbuf + width*height;
int hw = width / 2;
int hh = height / 2;
for (int i = 0; i <= hw - 1; i++){
for (int j = hh - 1; j >= 0; j--){
dstbuf[idx++] = *(uheader + (j*hw + i));
}
}
//V
unsigned char* vheader = uheader + width*height / 4;
for (int i = 0; i <= hw - 1; i++){
for (int j = hh - 1; j >= 0; j--){
dstbuf[idx++] = *(vheader + (j*hw + i));
}
}
FILE* fpout = NULL;
fopen_s(&fpout, "clockwiseRotate90.yuv", "wb");
fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
fclose(fpout);
delete[] yuvbuf;
delete[] dstbuf;
}
/** * Counter clockwise rotation 90. * Take the element : Start from the first point on the top right , From the top down , Take a point from right to left ; * Put the elements : Start from the first position on the top left , From left to right , From the top down ; Convert each column into each row . * * @param yuvFileaName One frame YUV420P File format * @param width The width of the image * @param height The height of the image * * @return empty */
void contrarotate90(const char* yuvFileaName, int width, int height)
{
int i, j, k, p;
FILE* fp = NULL;
fopen_s(&fp, yuvFileaName, "rb");
unsigned char* yuvbuf = new unsigned char[width*height * 3 / 2];
fread(yuvbuf, width*height * 3 / 2, 1, fp);
fclose(fp);
unsigned char* dstbuf = new unsigned char[width*height * 3 / 2];
char* dest = (char*)dstbuf;
char* src = (char*)yuvbuf;
// rotate Y
for (j = 0; j < width; j++){
for (i = 1; i <= height; i++){
*dest++ = *(src + i*width - j);
}
}
// rotate U
char *src_u = src + width*height;
for (p = 0; p < width / 2; p++){
for (k = 1; k <= height / 2; k++){
*dest++ = *(src_u + k*width / 2 - p);
}
}
// rotate V
char *src_v = src + width*height * 5 / 4;
for (p = 0; p < width / 2; p++){
for (k = 1; k <= height / 2; k++){
*dest++ = *(src_v + k*width / 2 - p);
}
}
FILE* fpout = NULL;
fopen_s(&fpout, "contrarotate90.yuv", "wb");
fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
fclose(fpout);
delete[] yuvbuf;
delete[] dstbuf;
}
/** * Anti-clockwise 180. * Take the element : Start at the first point on the lower right , From right to left , Take some from the bottom up ; * Put the elements : Start from the first position on the top left , From left to right , From the top down ; * * @param yuvFileaName One frame YUV420P File format * @param width The width of the image * @param height The height of the image * * @return empty */
void contrarotate180(const char* yuvFileaName, int width, int height){
FILE* fp = NULL;
fopen_s(&fp, yuvFileaName, "rb");
unsigned char* yuvbuf = new unsigned char[width*height * 3 / 2];
fread(yuvbuf, width*height * 3 / 2, 1, fp);
fclose(fp);
int idx = 0;
//Y
unsigned char* dstbuf = new unsigned char[width*height * 3 / 2];
for (int i = height - 1; i >= 0; i--){
for (int j = width - 1; j >= 0; j--){
dstbuf[idx++] = *(yuvbuf + (i*width + j));
}
}
//U
unsigned char* uheader = yuvbuf + width*height;
for (int i = height / 2 - 1; i >= 0; i--){
for (int j = width / 2 - 1; j >= 0; j--){
dstbuf[idx++] = *(uheader + (i*width / 2 + j));
}
}
unsigned char* vheader = uheader + width*height / 4;
//V
for (int i = height / 2 - 1; i >= 0; i--){
for (int j = width / 2 - 1; j >= 0; j--){
dstbuf[idx++] = *(vheader + (i*width / 2 + j));
}
}
FILE* fpout = NULL;
fopen_s(&fpout, "contrarotate180.yuv", "wb");
fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
fclose(fpout);
delete[] yuvbuf;
delete[] dstbuf;
}
/** * Mirror reversal / Flip horizontal * Take the element : Take the point in the upper right corner as the first point , From right to left , Take some from top to bottom ; * Put the elements : Start from the first position on the top left , From left to right , From the top down ; * * @param yuvFileaName One frame YUV420P File format * @param width The width of the image * @param height The height of the image * * @return empty */
void flipHorizontal(const char* yuvFileaName, int width, int height)
{
FILE* fp = NULL;
fopen_s(&fp, yuvFileaName, "rb");
unsigned char* yuvbuf = new unsigned char[width*height * 3 / 2];
fread(yuvbuf, width*height * 3 / 2, 1, fp);
fclose(fp);
int idx = 0;
//Y
unsigned char* dstbuf = new unsigned char[width*height * 3 / 2];
for (int i = 0; i < height; i++){
for (int j = width - 1; j >= 0; j--){
dstbuf[idx++] = *(yuvbuf + (i*width + j));
}
}
//U
unsigned char* uheader = yuvbuf + width*height;
for (int i = 0; i < height / 2; i++){
for (int j = width / 2 - 1; j >= 0; j--){
dstbuf[idx++] = *(uheader + (i*width / 2 + j));
}
}
//V
unsigned char* vheader = uheader + width*height / 4;
for (int i = 0; i < height / 2; i++){
for (int j = width / 2 - 1; j >= 0; j--){
dstbuf[idx++] = *(vheader + (i*width / 2 + j));
}
}
FILE* fpout = NULL;
fopen_s(&fpout, "flipHorizontal.yuv", "wb");
fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
fclose(fpout);
delete[] yuvbuf;
delete[] dstbuf;
}
/** * Counter clockwise rotation 180 after , Then flip horizontally / Mirror image . * Take the element : Start from the first point at the bottom left , From left to right , Take some from the bottom up ; * Put the elements : Start from the first position on the top left , From left to right , From the top down ; * * @param yuvFileaName One frame YUV420P File format * @param width The width of the image * @param height The height of the image * * @return empty */
void contrarotate180AndFlipHorizontal(const char* yuvFileaName, int width, int height){
FILE* fp = NULL;
fopen_s(&fp, yuvFileaName, "rb");
unsigned char* yuvbuf = new unsigned char[width*height * 3 / 2];
fread(yuvbuf, width*height * 3 / 2, 1, fp);
fclose(fp);
int idx = 0;
//Y wide
unsigned char* dstbuf = new unsigned char[width*height * 3 / 2];
for (int i = height - 1; i >= 0; i--){
for (int j = 0; j <= width - 1; j++){
dstbuf[idx++] = *(yuvbuf + (i*width + j));
}
}
//U
unsigned char* uheader = yuvbuf + width*height;
for (int i = height / 2 - 1; i >= 0; i--){
for (int j = 0; j <= width / 2 - 1; j++){
dstbuf[idx++] = *(uheader + (i*width / 2 + j));
}
}
//V
unsigned char* vheader = uheader + width*height / 4;
for (int i = height / 2 - 1; i >= 0; i--){
for (int j = 0; j <= width / 2 - 1; j++){
dstbuf[idx++] = *(vheader + (i*width / 2 + j));
}
}
FILE* fpout = NULL;
fopen_s(&fpout, "contrarotate180AndFlipHorizontal.yuv", "wb");
fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
fclose(fpout);
delete[] yuvbuf;
delete[] dstbuf;
}
int _tmain(int argc, _TCHAR* argv[])
{
const char* yuvFileaName = "yuv420p.yuv";
int w = 160;
int h = 128;
clockwiseRotate90(yuvFileaName, w, h);
contrarotate90(yuvFileaName, w, h);
contrarotate180(yuvFileaName, w, h);
flipHorizontal(yuvFileaName, w, h);
contrarotate180AndFlipHorizontal(yuvFileaName, w, h);
return 0;
}
边栏推荐
- [Luogu p1541] tortoise chess [DP]
- go 4種單例模式
- Go语言sqlx库操作SQLite3数据库增删改查
- Jerry's charge unplugged, unable to touch the boot [chapter]
- Qt QScrollArea
- 杰理之样机在多次触摸后会触发关机【篇】
- Webrtc audio and video capture and playback examples and mediastream media stream analysis
- 数据分析学习记录--用EXCEL完成简单的单因素方差分析
- P1007 single log bridge
- 性能优化----严苛模式
猜你喜欢
随机推荐
[羊城杯2020]easyphp
Analyse des données dossiers d'apprentissage - - analyse simple de la variance à facteur unique avec Excel
电路设计者常用的学习网站
數據分析學習記錄--用EXCEL完成簡單的單因素方差分析
Golang's learning route
antd组件upload上传xlsx文件,并读取文件内容
首批 | 腾讯云完成国内首个云原生安全成熟度评估
用sentinel熔断比例阈值改不了,设置慢调用比例没效果
Tronapi-波场接口-源码无加密-可二开--附接口文档-基于ThinkPHP5封装-作者详细指导-2022年7月1日08:43:06
杰理之快速触摸不响应问题【篇】
JS syntax ES6, ES7, es8, es9, ES10, es11, ES12 new features (Abstract)
Jerry's built-in shutdown current is 1.2ua, and then it can't be turned on by long pressing [chapter]
Distributed monitoring system ZABBIX
The threshold value of fusing proportion cannot be changed with sentinel, and setting the slow call proportion has no effect
编辑卡顿
【板栗糖GIS】arcmap—为什么使用自定义捕捉的时候,经典捕捉的勾要去掉呢?
PMP project integration management
Zhong Xuegao responded that the product will not melt for 1 hour: it contains solid components and cannot melt into water
海思3559万能平台搭建:在截获的YUV图像上画框
[chestnut sugar GIS] how does global mapper batch produce ground contour lines through DSM