东莞建外贸企业网站,淘宝客网站怎么做的人少了,苏州专业网站建设开发,深圳做生鲜食材的网站叫什么一. 应用场景#xff01;
使用过Genesis的朋友都知道#xff0c;它可以提取你点击单图元中心提取图元轮廓计算中心点#xff01; 二.
由于工作需要#xff0c;去年在师傅的知道下写了一个单图元轮廓提取算法#xff01; 三. 原理
提取轮廓即需要找出单图元最外…一. 应用场景
使用过Genesis的朋友都知道它可以提取你点击单图元中心提取图元轮廓计算中心点 二.
由于工作需要去年在师傅的知道下写了一个单图元轮廓提取算法 三. 原理
提取轮廓即需要找出单图元最外(内)层连续不间断的点
故我们需要一个起始点即从你点击的单图元出发向左(←↑→↓ 4个方向皆可只需改变算子的起始点)遍历至第一个与点击点不用色调的点此点极为最外层轮廓的起始点然后以你所选方向为算子起始项进行顺时针(逆时针)遍历直到遍历点与起始点重合说明轮廓提取完毕 四.
本例中我采用向左顺时针遍历剩余的7种就交给聪明的你了 1准备算子结构
1230*4765 typedef struct DOTS_ARR// 采用屏幕坐标Y轴向下{INT32 OffsetX;
// 相对中心点X向的偏移量INT32 OffsetY;
// 相对中心点Y向的偏移量INT32 NextDotIndex;
// 此点为目标点下次遍历位置索引}DOTS_ARR;2未优化算子DOTS_ARR DotsArr[] { -1, 0, 5, -1, -1, 6, 0, -1, 7, // 上图中当前计算点的正上方2号点若此点为最新提取的轮廓点则下一点应为此点相对位置7开始遍历原因如下 1, -1, 0, 1, 0, 1, 1, 1, 2, 0, 1, 3, -1, 1, 4, }; 为了保证不遗漏我们必须采取顺时针(逆时针)遍历当前点周围所有点以上次遍历成功2号点为例 12301*243706*54 括号中为以上以中心点为相对位置的坐标看到上图聪明的朋友一定会说7不是最好的位置1才是应为07在上次的遍历中已经被排除了you are right 故最优算子如下
DOTS_ARR DotsArr[] {
-1, 0, 5, -1, -1, 7, 0, -1, 1, 1, -1, 1, 1, 0, 3, 1, 1, 3, 0, 1, 5, -1, 1, 5, }; 五. Demo 关键的算子已经序数完了那么我用一个简单的Demo来实践一下
1先上一个提取后的效果图 2简单的列几处关键代码
1.创建一个简单窗口类单独用来绘制 m_MyView.CreateEx(NULL, AfxRegisterWndClass(CS_HREDRAW,NULL,(HBRUSH)::GetStockObject(WHITE_BRUSH),NULL), LCPaintView Window, WS_CHILD, m_MyViewRect, this, 0); if (NULL m_MyView) { TRACE(_T(Error:(%s.%d) CreateEx Failed!\r\n), __FUNCTION__, __LINE__); } 2.在窗口显示之前加载我们的位图
if (bShow)// Show { m_hMemDC CreateCompatibleDC(NULL); HBITMAP hBitmap LoadBitmapW(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP_START)); BITMAP bmp; GetObject(hBitmap, sizeof(BITMAP), bmp); m_BitmapSize.cx bmp.bmWidth; m_BitmapSize.cy bmp.bmHeight; m_hOldBitmap (HBITMAP)SelectObject(m_hMemDC, hBitmap); } else// Close { HBITMAP hBitmap (HBITMAP)SelectObject(m_hMemDC, m_hOldBitmap); DeleteObject(m_hOldBitmap); DeleteDC(m_hMemDC); } 注意一定要删除GDI对象做到万浪丛中过滴水不沾身否则会造成GDI泄漏(进程中GDI对象达到9999个此进程会奔溃) 3.在图元上打击做按钮时提取轮廓 #pragma region Get Contour Centerm_VectorContourPoint.clear();CDC *lpCDC GetDC();HDC hClientDC lpCDC-GetSafeHdc();RECT ContourRect {};POINT ptStart {};POINT ptErgod {point.x, point.y};COLORREF iColorValue GetPixel(hClientDC, point.x, point.y);while (iColorValue GetPixel(hClientDC, ptErgod.x , ptErgod.y)){ptErgod.x--;}if (-1 ptErgod.x){return;}ptErgod.x;memcpy(ptStart, ptErgod, sizeof(POINT));ContourRect.left ptStart.x;ContourRect.right ptStart.x;ContourRect.top ptStart.y;ContourRect.bottom ptStart.y;INT32 Count 0;INT32 FlagIndex 0;do {for (INT32 i 0; i DotsArrCount; i){if (iColorValue GetPixel(hClientDC, ptErgod.x DotsArr[FlagIndex].OffsetX, ptErgod.y DotsArr[FlagIndex].OffsetY)){Count;ptErgod.x DotsArr[FlagIndex].OffsetX;ptErgod.y DotsArr[FlagIndex].OffsetY;FlagIndex DotsArr[FlagIndex].NextDotIndex;m_VectorContourPoint.push_back(ptErgod);break;}FlagIndex;if (FlagIndex DotsArrCount){FlagIndex 0;}}ContourRect.left (ptErgod.x ContourRect.left) ? ptErgod.x : ContourRect.left;ContourRect.right (ptErgod.x ContourRect.right) ? ptErgod.x : ContourRect.right;ContourRect.top (ptErgod.y ContourRect.top) ? ptErgod.y : ContourRect.top;ContourRect.bottom (ptErgod.y ContourRect.bottom) ? ptErgod.y : ContourRect.bottom;} while (ptStart.x ! ptErgod.x || ptStart.y ! ptErgod.y);TRACE(Count is %d\r\n, Count);m_ptCenter.x (ContourRect.left ContourRect.right) 1;m_ptCenter.y (ContourRect.top ContourRect.bottom) 1;ReleaseDC(lpCDC);Invalidate(TRUE);
#pragma endregion4简单动态显示我们提取成果 BitBlt(dc.GetSafeHdc(), 0, 0, m_BitmapSize.cx, m_BitmapSize.cy, m_hMemDC, 0, 0, SRCCOPY);for (vectorPOINT::iterator itPoint m_VectorContourPoint.begin(); itPoint ! m_VectorContourPoint.end(); itPoint){if (itPoint m_VectorContourPoint.begin()){MoveToEx(dc.GetSafeHdc(), (*itPoint).x m_BitmapSize.cx, (*itPoint).y, NULL);}else{Sleep(1);LineTo(dc.GetSafeHdc(), itPoint-x m_BitmapSize.cx, itPoint-y);}}5完成运行过程中截图运行完成即为之前贴出的预览图 六.总结
师傅告诉我图像算法的处理要长期的积累自己去悟多思考当遇到一个新的算法需求结合自己的经验积累就能快速得到处理方法 有兴趣的朋友可以不使用Demo中Getpixel()而是直接处理位图数据块这样轮廓提取的效率会更高 这也是我去年学到第一个算法处理的在这一年中自己也积累了一些简单的图像处理算法如灰度淡化(抽点)多图元骨架提取等 最后希望图像处理大神不啬指出demo中的不足以及需要优化之处谢谢 七Demo源码下载地址
http://download.csdn.net/detail/u012158162/9590647