当前位置:网站首页>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;
}
边栏推荐
- Generics and reflection, this is enough
- Share 10 JS closure interview questions (diagrams), come in and see how many you can answer correctly
- Jatpack------LiveData
- stop slave卡住--事务的事件没有复制完整
- QT qsplitter splitter
- antd组件upload上传xlsx文件,并读取文件内容
- 全面解析分享购商业模式逻辑?分享购是如何赋能企业
- MySQL查询附近的数据.并按距离进行排序.
- boot actuator - prometheus使用
- 【板栗糖GIS】arcmap—为什么使用自定义捕捉的时候,经典捕捉的勾要去掉呢?
猜你喜欢
随机推荐
[羊城杯2020]easyphp
Qt QScrollArea
【板栗糖GIS】global mapper 如何通过dsm批量制作贴地等高线
Kubernetes uses the host name to allocate the pod on the specified node
Solve the error of changing the selected file when uploading excel file. Net:: err_ UPLOAD_ FILE_ CHANGED
【板栗糖GIS】arcmap—为什么使用自定义捕捉的时候,经典捕捉的勾要去掉呢?
Array advanced improvement
[leetcode] most elements [169]
性能优化----严苛模式
Webrtc audio and video capture and playback examples and mediastream media stream analysis
xshell配置xforward转发火狐浏览器
加油站[问题分析->问题转换->贪心]
[LeetCode] 反转字符串【344】
PMP项目整合管理
Motivation du Protocole de chiffrement avancé AES
LeetCode 968. Monitor binary tree
Storage unit conversion
Share 10 JS closure interview questions (diagrams), come in and see how many you can answer correctly
Golang的学习路线
最小生成树 Minimum Spanning Tree