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 }