• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <iostream>
17 #include <opencv2/core.hpp>
18 #include <opencv2/highgui.hpp>
19 #include <opencv2/imgproc.hpp>
20 #include "tennis_detect.h"
21 
22 #include "sample_comm_nnie.h"
23 #include "sample_comm_ive.h"
24 #include "sample_media_ai.h"
25 #include "vgs_img.h"
26 #include "misc_util.h"
27 
28 using namespace std;
29 using namespace cv;
30 
31 static IVE_SRC_IMAGE_S pstSrc;
32 static IVE_DST_IMAGE_S pstDst;
33 static IVE_CSC_CTRL_S stCscCtrl;
34 
IveImageParamCfg(IVE_SRC_IMAGE_S * pstSrc,IVE_DST_IMAGE_S * pstDst,VIDEO_FRAME_INFO_S * srcFrame)35 static HI_VOID IveImageParamCfg(IVE_SRC_IMAGE_S *pstSrc, IVE_DST_IMAGE_S *pstDst,
36     VIDEO_FRAME_INFO_S *srcFrame)
37 {
38     pstSrc->enType = IVE_IMAGE_TYPE_YUV420SP;
39     pstSrc->au64VirAddr[0] = srcFrame->stVFrame.u64VirAddr[0];
40     pstSrc->au64VirAddr[1] = srcFrame->stVFrame.u64VirAddr[1];
41     pstSrc->au64VirAddr[2] = srcFrame->stVFrame.u64VirAddr[2]; // 2: Image data virtual address
42 
43     pstSrc->au64PhyAddr[0] = srcFrame->stVFrame.u64PhyAddr[0];
44     pstSrc->au64PhyAddr[1] = srcFrame->stVFrame.u64PhyAddr[1];
45     pstSrc->au64PhyAddr[2] = srcFrame->stVFrame.u64PhyAddr[2]; // 2: Image data physical address
46 
47     pstSrc->au32Stride[0] = srcFrame->stVFrame.u32Stride[0];
48     pstSrc->au32Stride[1] = srcFrame->stVFrame.u32Stride[1];
49     pstSrc->au32Stride[2] = srcFrame->stVFrame.u32Stride[2]; // 2: Image data span
50 
51     pstSrc->u32Width = srcFrame->stVFrame.u32Width;
52     pstSrc->u32Height = srcFrame->stVFrame.u32Height;
53 
54     pstDst->enType = IVE_IMAGE_TYPE_U8C3_PACKAGE;
55     pstDst->u32Width = pstSrc->u32Width;
56     pstDst->u32Height = pstSrc->u32Height;
57     pstDst->au32Stride[0] = pstSrc->au32Stride[0];
58     pstDst->au32Stride[1] = 0;
59     pstDst->au32Stride[2] = 0; // 2: Image data span
60 }
61 
yuvFrame2rgb(VIDEO_FRAME_INFO_S * srcFrame,IPC_IMAGE * dstImage)62 static HI_S32 yuvFrame2rgb(VIDEO_FRAME_INFO_S *srcFrame, IPC_IMAGE *dstImage)
63 {
64     IVE_HANDLE hIveHandle;
65     HI_S32 s32Ret = 0;
66     stCscCtrl.enMode = IVE_CSC_MODE_PIC_BT709_YUV2RGB; // IVE_CSC_MODE_VIDEO_BT601_YUV2RGB
67     IveImageParamCfg(&pstSrc, &pstDst, srcFrame);
68 
69     s32Ret = HI_MPI_SYS_MmzAlloc_Cached(&pstDst.au64PhyAddr[0], (void **)&pstDst.au64VirAddr[0],
70         "User", HI_NULL, pstDst.u32Height*pstDst.au32Stride[0] * 3); // 3: multiple
71     if (HI_SUCCESS != s32Ret) {
72         HI_MPI_SYS_MmzFree(pstDst.au64PhyAddr[0], (void *)pstDst.au64VirAddr[0]);
73         SAMPLE_PRT("HI_MPI_SYS_MmzFree err\n");
74         return s32Ret;
75     }
76 
77     s32Ret = HI_MPI_SYS_MmzFlushCache(pstDst.au64PhyAddr[0], (void *)pstDst.au64VirAddr[0],
78         pstDst.u32Height*pstDst.au32Stride[0] * 3); // 3: multiple
79     if (HI_SUCCESS != s32Ret) {
80         HI_MPI_SYS_MmzFree(pstDst.au64PhyAddr[0], (void *)pstDst.au64VirAddr[0]);
81         return s32Ret;
82     }
83     // 3: multiple
84     memset_s((void *)pstDst.au64VirAddr[0], pstDst.u32Height*pstDst.au32Stride[0] * 3,
85         0, pstDst.u32Height*pstDst.au32Stride[0] * 3); // 3: multiple
86     HI_BOOL bInstant = HI_TRUE;
87 
88     s32Ret = HI_MPI_IVE_CSC(&hIveHandle, &pstSrc, &pstDst, &stCscCtrl, bInstant);
89     if (HI_SUCCESS != s32Ret) {
90         HI_MPI_SYS_MmzFree(pstDst.au64PhyAddr[0], (void *)pstDst.au64VirAddr[0]);
91         return s32Ret;
92     }
93 
94     if (HI_TRUE == bInstant) {
95         HI_BOOL bFinish = HI_TRUE;
96         HI_BOOL bBlock = HI_TRUE;
97         s32Ret = HI_MPI_IVE_Query(hIveHandle, &bFinish, bBlock);
98         while (HI_ERR_IVE_QUERY_TIMEOUT == s32Ret) {
99             usleep(100); // 100: usleep time
100             s32Ret = HI_MPI_IVE_Query(hIveHandle, &bFinish, bBlock);
101         }
102     }
103     dstImage->u64PhyAddr = pstDst.au64PhyAddr[0];
104     dstImage->u64VirAddr = pstDst.au64VirAddr[0];
105     dstImage->u32Width = pstDst.u32Width;
106     dstImage->u32Height = pstDst.u32Height;
107 
108     return HI_SUCCESS;
109 }
110 
frame2Mat(VIDEO_FRAME_INFO_S * srcFrame,Mat & dstMat)111 static HI_S32 frame2Mat(VIDEO_FRAME_INFO_S *srcFrame, Mat &dstMat)
112 {
113     HI_U32 w = srcFrame->stVFrame.u32Width;
114     HI_U32 h = srcFrame->stVFrame.u32Height;
115     int bufLen = w * h * 3;
116     HI_U8 *srcRGB = NULL;
117     IPC_IMAGE dstImage;
118     if (yuvFrame2rgb(srcFrame, &dstImage) != HI_SUCCESS) {
119         SAMPLE_PRT("yuvFrame2rgb err\n");
120         return HI_FAILURE;
121     }
122     srcRGB = (HI_U8 *)dstImage.u64VirAddr;
123     dstMat.create(h, w, CV_8UC3);
124     memcpy_s(dstMat.data, bufLen * sizeof(HI_U8), srcRGB, bufLen * sizeof(HI_U8));
125     HI_MPI_SYS_MmzFree(dstImage.u64PhyAddr, (void *)&(dstImage.u64VirAddr));
126     return HI_SUCCESS;
127 }
128 
TennisDetectLoad(uintptr_t * model)129 HI_S32 tennis_detect::TennisDetectLoad(uintptr_t* model)
130 {
131     HI_S32 ret = 1;
132     *model = 1;
133     SAMPLE_PRT("TennisDetectLoad success\n");
134 
135     return ret;
136 }
137 
TennisDetectUnload(uintptr_t model)138 HI_S32 tennis_detect::TennisDetectUnload(uintptr_t model)
139 {
140     model = 0;
141 
142     return HI_SUCCESS;
143 }
144 
TennisDetectCal(uintptr_t model,VIDEO_FRAME_INFO_S * srcFrm,VIDEO_FRAME_INFO_S * dstFrm)145 HI_S32 tennis_detect::TennisDetectCal(uintptr_t model, VIDEO_FRAME_INFO_S *srcFrm, VIDEO_FRAME_INFO_S *dstFrm)
146 {
147     (void)model;
148     int ret = 0;
149     RectBox boxs[32] = {0}; // 32: TENNIS_OBJ_MAX
150     int j = 0;
151 
152     Mat image;
153     frame2Mat(srcFrm, image);
154     if (image.size == 0) {
155         SAMPLE_PRT("image is null\n");
156         return HI_FAILURE;
157     }
158 
159     Mat src = image;
160     Mat src1 = src.clone();
161     Mat dst, edge, gray, hsv;
162 
163     dst.create(src1.size(), src1.type()); // Create a matrix of the same type and size as src (dst)
164 
165     // The cvtColor operator is used to convert an image from one color space to another color space
166     cvtColor(src1, hsv, COLOR_BGR2HSV); // Convert original image to HSV image
167 
168     // Binarize the hsv image, here is to binarize the green background,
169     // this parameter can be adjusted according to requirements
170     inRange(hsv, Scalar(31, 82, 68), Scalar(65, 248, 255), gray); // 31: B, 82: G, 68:R / 65: B, 248:G, 255:R
171 
172     // Use canny operator for edge detection
173     // 3: threshold1, 9: threshold2, 3: apertureSize
174     Canny(gray, gray, 3, 9, 3);
175     vector<vector<Point>> contours;
176     findContours(gray, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());
177     SAMPLE_PRT("contours.size():%d\n", contours.size());
178 
179     for (int i = 0; i < (int)contours.size(); i++) {
180         if (contours.size() > 40) { // 40: contours.size() extremes
181             continue;
182         }
183 
184         Rect ret1 = boundingRect(Mat(contours[i]));
185         ret1.x -= 5; // 5: x coordinate translation
186         ret1.y -= 5; // 5: y coordinate translation
187         ret1.width += 10; // 10: Rectangle width plus 10
188         ret1.height += 10; // 10: Rectangle height plus 10
189 
190         // 20: Rectangle width and height pixel extremes
191         if ((ret1.width > 20) && (ret1.height > 20)) {
192             boxs[j].xmin = ret1.x * 3; // 3: optimized value
193             boxs[j].ymin = (int)(ret1.y * 2.25); // 2.25: optimized value
194             boxs[j].xmax = boxs[j].xmin + ret1.width * 3; // 3: optimized value
195             boxs[j].ymax = boxs[j].ymin + (int)ret1.height * 2.25; // 2.25: optimized value
196             j++;
197         }
198     }
199     // 25: detect boxesNum
200     if (j > 0 && j <= 25) {
201         SAMPLE_PRT("box num:%d\n", j);
202         MppFrmDrawRects(dstFrm, boxs, j, RGB888_RED, 2); // 2: DRAW_RETC_THICK
203     }
204 
205     return ret;
206 }