Stitch

通过拼接,实现将一张图片与另一张图片拼接融合的效果,常用于APA和全景图拼接等场景。

算子效果

输入图像位置输出图像
VP5input_stitch_apa_top前视VP5out_apa_res
VP5input_stitch_apa_bottom后视
VP5input_stitch_apa_right右视
VP5input_stitch_apa_left左视
VP5input_stitch_dst底层图

原理

如果是拼接模式,将两张图做拼接粘贴至dst图层,那么公式如下:

dst(x,y)=src0(x,y)alpha+src1(x,y)(255alpha)dst(x, y) = src0(x, y) * alpha + src1(x, y) * (255-alpha)

其中, dst 是输出图片,src0 是输入图片0,src1 是输入图片1。 src0像素点乘以alpha系数,另一张图的对应像素点乘以beta系数,将两个结果相加,更新dst图层的像素点。

VP5input_stitch_blend

如果是粘贴原图模式,将一张图粘贴至dst图层,那么公式如下:

dst(x,y)=src(x,y)dst(x, y) = src(x, y)

其中, dst 是输出图片,src 是输入图片。 使用src像素点,更新dst图层的像素点。

VP5input_stitch_copy

lut表,就是由上述n个alpha组成的,能够表示w*h区域每个像素点融合情况的表。通过配置每个像素点不同的alpha值,可以实现不同的拼接值。

VP5input_stitch_lut

API接口

int32_t hbVPStitch(hbUCPTaskHandle_t *taskHandle, hbVPImage *dstImg, hbVPImage const *srcImgs, hbVPPoint const *dstPoses, int32_t srcImgCount, hbVPAlphaBlendLut alphaBlendLut);

详细接口信息请查看 hbVPStitch

使用方法

// Include the header #include "hobot/hb_ucp.h" #include "hobot/vp/hb_vp.h" #include "hobot/vp/hb_vp_stitch.h" // init param int32_t alphaBlendRegionNum{1}; std::vector<uint8_t> alpha(320 * 160); memset(alpha.data(), uint8_t(200), 320 * 160); std::vector<uint8_t *> alphaDataArray = {alpha.data()}; std::vector<hbVPRoi> alphaBlendRegions = {{320, 0, 480 - 1, 320 - 1}}; // create alpha-blend lut hbVPAlphaBlendLut alphaBlendLut{nullptr}; hbVPCreateAlphaBlendLut(&alphaBlendLut, alphaDataArray.data(), alphaBlendRegions.data(), alphaBlendRegionNum); // init task handle and schedule param hbUCPTaskHandle_t task_handle{nullptr}; hbUCPSchedParam sched_param; HB_UCP_INITIALIZE_SCHED_PARAM(&sched_param); sched_param.backend = HB_UCP_STITCH_CORE_0; // init Image, allocate memory for image data int32_t srcImgCount{2}; std::vector<hbUCPSysMem> src_mems(srcImgCount); std::vector<hbVPImage> src_imgs(srcImgCount); for (int32_t i{0}; i < srcImgCount; i++) { hbUCPMallocCached(&src_mems[i], src_stride * src_height, 0); src_imgs[i] = {HB_VP_IMAGE_FORMAT_NV12, HB_VP_IMAGE_TYPE_U8C1, src_width, src_height, src_stride, src_mems[i].virAddr, src_mems[i].phyAddr, reinterpret_cast<char *>(src_imgs[i].dataVirAddr) + src_stride * src_height, src_imgs[i].dataPhyAddr + src_stride * src_height, src_stride}; } std::vector<hbVPPoint> dstPoses(srcImgCount); dstPoses[0] = {160, 0}; dstPoses[1] = {320, 0}; hbUCPSysMem dst_mem; hbUCPMallocCached(&dst_mem, dst_stride * dst_height * 3 / 2, 0); hbVPImage dst_img{HB_VP_IMAGE_FORMAT_NV12, HB_VP_IMAGE_TYPE_U8C1, dst_width, dst_height, dst_stride, dst_mem.virAddr, dst_mem.phyAddr, reinterpret_cast<char *>(dst_img.dataVirAddr) + dst_stride * dst_height, dst_img.dataPhyAddr + dst_stride * dst_height, dst_stride}; // create task hbVPStitch(&task_handle, &dst_img, src_imgs.data(), dstPoses.data(), srcImgCount, alphaBlendLut); // submit task hbUCPSubmitTask(task_handle, &sched_param); // wait for task done hbUCPWaitTaskDone(task_handle, 0); // release task handle hbUCPReleaseTask(task_handle); // release alpha-blend lut hbVPReleaseAlphaBlendLut(alphaBlendLut); // release memory for (int32_t i{0}; i < srcImgCount; i++) { hbUCPFree(&src_mems[i]); } hbUCPFree(&dst_mem);