目的:对于很暗很暗的图像 用普通方法不好一下找到轮廓 现在需要找到其最接近的轮廓

像这样的图像  拍的是一块完整的石头  蓝色部分只是石头的反光部分而已  现在是要找到这个石头的轮廓  最终得到它的面积。

#include<opencv2/opencv.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include <afxwin.h>
#include<fstream>
using namespace std;
using namespace cv;Mat my_contour(IplImage* dst, IplImage bimgipl)
{cvZero(dst);CvMemStorage *storage = cvCreateMemStorage();CvSeq *contour = NULL, *hull = NULL;vector<CvPoint> allpoints;CvContourScanner scanner = cvStartFindContours(&bimgipl, storage);while ((contour = cvFindNextContour(scanner)) != NULL){cvDrawContours(dst, contour, cv::Scalar(255), cv::Scalar(255), 0);hull = cvConvexHull2(contour, 0, CV_CLOCKWISE, 0);CvPoint pt0 = **(CvPoint**)cvGetSeqElem(hull, hull->total - 1);allpoints.push_back(pt0);for (int i = 0; i < hull->total; ++i){CvPoint pt1 = **(CvPoint**)cvGetSeqElem(hull, i);allpoints.push_back(pt1);cvLine(dst, pt0, pt1, cv::Scalar(255));pt0 = pt1;}}//上面是第一次寻找 可能找到了多个轮廓即有多个凸包 下面存储每个凸包的凸点到容器中 然后将这些点连接起来 这样就有凹陷的地方了 就可以在此基础上寻找最后的凸包了 Mat dstmat(dst, 0);std::vector<std::vector<cv::Point>> myown_contours;cv::findContours(dstmat, myown_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//判断也许本来就只有一个凸包 就不用存点画线再寻一次凸包了if (myown_contours.size() > 1){for (int i = 0; i < allpoints.size() - 1; i++){CvPoint firstdot = allpoints[i];CvPoint secdot = allpoints[i + 1];cvLine(dst, firstdot, secdot, cv::Scalar(255), 2);}CvContourScanner scanner2 = cvStartFindContours(dst, storage);while ((contour = cvFindNextContour(scanner2)) != NULL){cvDrawContours(dst, contour, cv::Scalar(255), cv::Scalar(255), 0);hull = cvConvexHull2(contour, 0, CV_CLOCKWISE, 0);CvPoint pt0 = **(CvPoint**)cvGetSeqElem(hull, hull->total - 1);for (int i = 0; i < hull->total; ++i){CvPoint pt1 = **(CvPoint**)cvGetSeqElem(hull, i);cvLine(dst, pt0, pt1, cv::Scalar(255));pt0 = pt1;}}}Mat bimgdst(dst, 0);std::vector<std::vector<cv::Point>> contours;cv::findContours(bimgdst, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);Mat contoursimg(bimgdst.size(), CV_8UC1, cv::Scalar(0));drawContours(contoursimg, contours, -1, Scalar(255), CV_FILLED);return contoursimg;
}char filename[100];
char savename[100];void main()
{TickMeter tm;tm.start();vector<Mat> bgrimgs;for (int i = 1; i <= 1657; i++){sprintf(filename, "正常图_压缩\\%d.bmp", i);sprintf(savename, "my_result3\\%d.bmp", i);Mat img = imread(filename);//split(img, bgrimgs);Mat bimg(img.size(), CV_8UC1, cv::Scalar(0));bgrimgs[0].copyTo(bimg);//     threshold(bimg, bimg, 12, 255, CV_THRESH_BINARY/*|CV_THRESH_OTSU*/);//imshow("thresh result", bimg);//Mat element(4, 4, CV_8U, cv::Scalar(1));morphologyEx(bimg, bimg, cv::MORPH_OPEN, element);//imshow("dilate result", bimg);//前20行置0 去除上部分的水滴噪声 后20行也置0 去除下面的噪声/*  //这个置0没有下面写的置0好 用下面的IplImage bimgipl = bimg;cvSetImageROI(&bimgipl, cvRect(0, 0, bimg.size().width,20));IplImage* bimg_front = cvCreateImage(cvSize(bimg.size().width, 20), IPL_DEPTH_8U, 1);cvCopy(&bimgipl, bimg_front, 0);cvShowImage("front", bimg_front);cvSetImageROI(&bimgipl, cvRect(0, bimg.size().height-20, bimg.size().width, 20));IplImage* bimg_end = cvCreateImage(cvSize(bimg.size().width, 20), IPL_DEPTH_8U, 1);cvCopy(&bimgipl, bimg_end, 0);cvShowImage("end", bimg_end);cvZero(bimg_front);cvZero(bimg_end);*/for (int i = 0; i < 20; i++){uchar* data = bimg.ptr<uchar>(i);for (int j = 0; j < bimg.size().width; j++)data[j] = 0;}for (int i = bimg.size().height - 19; i < bimg.size().height; i++){uchar* data = bimg.ptr<uchar>(i);for (int j = 0; j < bimg.size().width; j++)data[j] = 0;}//凸包找轮廓 (我用了2次凸包 中间用线连接 方便第二次凸包 找到完整轮廓)IplImage mybimgipl = bimg;IplImage *mydst = cvCreateImage(cvGetSize(&mybimgipl), 8, 1);Mat myresult(mydst, 0);myresult = my_contour(mydst, mybimgipl);imwrite(savename, myresult);}tm.stop();cout << "count=" << tm.getCounter() << ",process time=" << tm.getTimeMilli() << " ms" << endl;}

拿一种一张图的中间结果来说:

分别是阈值化 开操作 第一次凸包 第一次凸包填充后的结果

左图就是对于第一次凸包连线后 再凸包后的结果   右边就是对左图填充后的结果   也是最终结果!
done!!!!今天星期五!好开心!!!!!!!!!!!!

关于opencv中找轮廓的 : http://www.cnblogs.com/nktblog/p/4027137.html   写得很棒

给学校我自习室的电脑上装了opencv2.4.13 按照http://blog.csdn.net/dcrmg/article/details/51809614

看到巴卫和奈奈生就开心。。。。。。

//

我公司的同事说我这个比较慢  他在网上 https://github.com/abatilo/QuickHull 找到一个快速找凸包的叫我应用进来:于是我重新又写了个:

#include <algorithm>
#include <cmath>
#include <vector>
#include <chrono>
#include <cstdio>
#include <random>
#include <vector>#include<opencv2/opencv.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;struct myPoint {int x;int y;bool operator<(const myPoint& pt) {if (x == pt.x) {return (y < pt.y);}return (x < pt.x);}
};// http://stackoverflow.com/questions/1560492/how-to-tell-whether-a-myPoint-is-to-the-right-or-left-side-of-a-line
// A and B are used to define a line
// C is the myPoint whose side we're trying to determine
int SideOfLine(const myPoint &P1, const myPoint &P2, const myPoint &P3) {return (P2.x - P1.x) * (P3.y - P1.y) - (P2.y - P1.y) * (P3.x - P1.x);
}// https://en.wikipedia.org/wiki/Distance_from_a_myPoint_to_a_line#Line_defined_by_two_myPoints
float DistanceFromLine(const myPoint &P1, const myPoint &P2, const myPoint &P3) {return (std::abs((P2.y - P1.y) * P3.x - (P2.x - P1.x) * P3.y + P2.x * P1.y - P2.y * P1.x)/ std::sqrt((P2.y - P1.y) * (P2.y - P1.y) + (P2.x - P1.x) * (P2.x - P1.x)));
}// http://stackoverflow.com/questions/13300904/determine-whether-myPoint-lies-inside-triangle
bool myPointInTriangle(const myPoint &p, const myPoint &p1, const myPoint &p2, const myPoint &p3) {float a = ((p2.y - p3.y) * (p.x - p3.x) + (p3.x - p2.x) * (p.y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));float b = ((p3.y - p1.y) * (p.x - p3.x) + (p1.x - p3.x) * (p.y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));float c = 1.0f - a - b;return (0.0f < a && 0.0f < b && 0.0f < c);
}// http://www.cse.yorku.ca/~aaw/Hang/quick_hull/Algorithm.html
void FindHull(const std::vector<myPoint> &Sk, const myPoint P, const myPoint Q, std::vector<myPoint> &hullmyPoints) {// If Sk has no myPoint, then  returnif (Sk.size() == 0) return;std::vector<myPoint> S0;std::vector<myPoint> S1;std::vector<myPoint> S2;// From the given set of myPoints in Sk, find farthest myPoint, say C, from segment PQ float furthestDistance = 0.0f;myPoint C;for (const auto &pt : Sk) {float distance = DistanceFromLine(P, Q, pt);if (distance > furthestDistance) {furthestDistance = distance;C = pt;}}// Add myPoint C to convex hull at the location between P and Q hullmyPoints.push_back(C);/** Three myPoints P, Q, and C partition the remaining myPoints of Sk into 3 subsets: S0, S1, and S2* where S0 are myPoints inside triangle PCQ, S1are myPoints on the right side of the oriented* line from  P to C, and S2 are myPoints on the right side of the oriented line from C to Q.*/for (const auto &pt : Sk) {if (myPointInTriangle(pt, P, C, Q)) {S0.push_back(pt);}else if (0 < SideOfLine(P, C, pt)) {S1.push_back(pt);}else if (0 < SideOfLine(C, Q, pt)) {S2.push_back(pt);}}FindHull(S1, P, C, hullmyPoints);FindHull(S2, C, Q, hullmyPoints);
}// http://www.cse.yorku.ca/~aaw/Hang/quick_hull/Algorithm.html
void QuickHull(const std::vector<myPoint> &s, std::vector<myPoint> &hullmyPoints) {// Find left and right most myPoints, say A & B, and add A & B to convex hull myPoint A = s[0];myPoint B = s[s.size() - 1];hullmyPoints.push_back(A);hullmyPoints.push_back(B);std::vector<myPoint> S1;std::vector<myPoint> S2;/** Segment AB divides the remaining (n-2) myPoints into 2 groups S1 and S2* where S1 are myPoints in S that are on the right side of the oriented line from A to B,* and S2 are myPoints in S that are on the right side of the oriented line from B to A*/for (auto it = s.begin() + 1; it != s.end() - 1; ++it) {const myPoint pt = *it;const int s1 = SideOfLine(A, B, pt);const int s2 = SideOfLine(B, A, pt);if (0 < s1) {S1.push_back(pt);}else if (0 < s2) {S2.push_back(pt);}}FindHull(S1, A, B, hullmyPoints);FindHull(S2, B, A, hullmyPoints);
}Mat mypredone(IplImage* srcipl, vector<Mat> bgrimgs)
{预处理Mat img(srcipl, 0);split(img, bgrimgs);Mat bimg(img.size(), CV_8UC1, cv::Scalar(0));bgrimgs[0].copyTo(bimg);threshold(bimg, bimg, 12, 255, CV_THRESH_BINARY/*|CV_THRESH_OTSU*/);Mat element(4, 4, CV_8U, cv::Scalar(1));morphologyEx(bimg, bimg, cv::MORPH_OPEN, element);for (int i = 0; i < 20; i++){uchar* data = bimg.ptr<uchar>(i);for (int j = 0; j < bimg.size().width; j++)data[j] = 0;}//for (int i = bimg.size().height - 19; i < bimg.size().height; i++)//{// uchar* data = bimg.ptr<uchar>(i);//  for (int j = 0; j < bimg.size().width; j++)//     data[j] = 0;//}return bimg;
}IplImage* luobin_findcontour(Mat bimg)
{IplImage mybimgipl = bimg;CvMemStorage *storage = cvCreateMemStorage();CvSeq *contour = NULL, *hull = NULL;vector<CvPoint> allpoints;vector<myPoint> myallpoints;CvContourScanner scanner = cvStartFindContours(&mybimgipl, storage);while ((contour = cvFindNextContour(scanner)) != NULL){hull = cvConvexHull2(contour, 0, CV_CLOCKWISE, 0);CvPoint pt0 = **(CvPoint**)cvGetSeqElem(hull, hull->total - 1);myPoint mypt0;mypt0.x = (float)pt0.x;mypt0.y = (float)pt0.y;mypt0.operator<(mypt0);  allpoints.push_back(pt0);myallpoints.push_back(mypt0);for (int i = 0; i < hull->total; ++i){CvPoint pt1 = **(CvPoint**)cvGetSeqElem(hull, i);allpoints.push_back(pt1);//cvLine(mydst, pt0, pt1, cv::Scalar(255));//pt0 = pt1;myPoint mypt1;mypt1.x = (float)pt1.x;mypt1.y = (float)pt1.y;mypt1.operator<(mypt1);  //myallpoints.push_back(mypt1);}}std::sort(myallpoints.begin(), myallpoints.end());std::vector<myPoint> myhullPoints;QuickHull(myallpoints, myhullPoints);CvSeq *hull2 = NULL;CvSeq* ptseq = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2, sizeof(CvContour), sizeof(CvPoint), storage);for (int i = 0; i < myhullPoints.size(); ++i){myPoint pt1 = myhullPoints[i];CvPoint myfinalpot1;myfinalpot1.x = pt1.x;myfinalpot1.y = pt1.y;cvSeqPush(ptseq, &myfinalpot1);}hull2 = cvConvexHull2(ptseq, 0, CV_CLOCKWISE, 1);IplImage *mydst3 = cvCreateImage(cvGetSize(&mybimgipl), 8, 1);cvZero(mydst3);cvDrawContours(mydst3, hull2, CV_RGB(255, 255, 255), CV_RGB(255, 255, 255), -1, CV_FILLED, 8);return mydst3;
}char filename[100];
char newcontour[100];void main()
{IplImage* src_ipl = cvLoadImage("12.bmp");cvShowImage("srcimage", src_ipl);vector<Mat> bgrimgs;Mat bimg = mypredone(src_ipl, bgrimgs);IplImage* luobin_result = luobin_findcontour(bimg);cvShowImage("luobin result2", luobin_result);waitKey(0);/*TickMeter tm;tm.start();for (int i = 55124; i <= 56460; i++){int newi = i - 55123;sprintf(filename, "背面图\\%d.bmp", i);sprintf(newcontour, "罗彬背面轮廓\\%d.bmp", newi);IplImage* src_ipl = cvLoadImage(filename);vector<Mat> bgrimgs;Mat bimg = mypredone(src_ipl, bgrimgs);IplImage* luobin_result = luobin_findcontour(bimg);cvSaveImage(newcontour, luobin_result);}tm.stop();cout << "count=" << tm.getCounter() << ",process time=" << tm.getTimeMilli() << endl;*/
}

和上面我自己的算法是同一张原图  的确比我的快了将近一倍!

但对带噪声的图,直接用上面这个快速凸包寻找轮廓的办法就不行:

我把原图、灰度图、上面这个快速凸包找轮廓的图、我后一篇自己写的结果图  对比了一下:

char filename[100];
char newcontour[100];
char grayimg[100];
char myback[100];
char contrast[100];void main()
{TickMeter tm;tm.start();CvSize mysize = cvSize(484 * 4, 364);for (int i = 1; i <= 1337; i++){sprintf(filename, "背面图\\%d.bmp", i);sprintf(newcontour, "罗彬背面轮廓\\%d.bmp", i);sprintf(grayimg, "背面灰度\\%d.bmp", i);sprintf(myback, "我的背面轮廓\\%d.bmp", i); sprintf(contrast, "背面对比图\\%d.bmp", i);IplImage* left = cvLoadImage(filename);IplImage* combine = cvCreateImage(mysize, left->depth, left->nChannels);cvZero(combine); cvSetImageROI(combine, cvRect(0, 0, left->width, left->height)); cvCopy(left, combine);cvResetImageROI(combine);IplImage* right = cvLoadImage(grayimg);cvSetImageROI(combine, cvRect(483, 0, right->width, right->height));cvCopy(right, combine);cvResetImageROI(combine);IplImage* right2 = cvLoadImage(newcontour);cvSetImageROI(combine, cvRect(484*2-1, 0, right2->width, right2->height));cvCopy(right2, combine);cvResetImageROI(combine);IplImage* right3 = cvLoadImage(myback);cvSetImageROI(combine, cvRect(484 * 3 - 1, 0, right3->width, right3->height));cvCopy(right3, combine);cvResetImageROI(combine);cvSaveImage(contrast, combine);}tm.stop();cout << "count=" << tm.getCounter() << ",process time=" << tm.getTimeMilli() << endl;
}

所以 对有杂质的还是不能够直接用  还需要修改。
最终改成了:

#include <algorithm>
#include <cmath>
#include <vector>
#include <chrono>
#include <cstdio>
#include <random>
#include <vector>
#include<opencv2/opencv.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;struct myPoint {int x;int y;bool operator<(const myPoint& pt) {if (x == pt.x){return (y < pt.y);}return (x < pt.x);}
};// http://stackoverflow.com/questions/1560492/how-to-tell-whether-a-myPoint-is-to-the-right-or-left-side-of-a-line
int SideOfLine(const myPoint &P1, const myPoint &P2, const myPoint &P3) {return (P2.x - P1.x) * (P3.y - P1.y) - (P2.y - P1.y) * (P3.x - P1.x);
}// https://en.wikipedia.org/wiki/Distance_from_a_myPoint_to_a_line#Line_defined_by_two_myPoints
float DistanceFromLine(const myPoint &P1, const myPoint &P2, const myPoint &P3) {return (std::abs((P2.y - P1.y) * P3.x - (P2.x - P1.x) * P3.y + P2.x * P1.y - P2.y * P1.x)/ std::sqrt((P2.y - P1.y) * (P2.y - P1.y) + (P2.x - P1.x) * (P2.x - P1.x)));
}// http://stackoverflow.com/questions/13300904/determine-whether-myPoint-lies-inside-triangle
bool myPointInTriangle(const myPoint &p, const myPoint &p1, const myPoint &p2, const myPoint &p3) {float a = ((p2.y - p3.y) * (p.x - p3.x) + (p3.x - p2.x) * (p.y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));float b = ((p3.y - p1.y) * (p.x - p3.x) + (p1.x - p3.x) * (p.y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));float c = 1.0f - a - b;return (0.0f < a && 0.0f < b && 0.0f < c);
}// http://www.cse.yorku.ca/~aaw/Hang/quick_hull/Algorithm.html
void FindHull(const std::vector<myPoint> &Sk, const myPoint P, const myPoint Q, std::vector<myPoint> &hullmyPoints) {if (Sk.size() == 0) return;std::vector<myPoint> S0;std::vector<myPoint> S1;std::vector<myPoint> S2;float furthestDistance = 0.0f;myPoint C;for (const auto &pt : Sk) {float distance = DistanceFromLine(P, Q, pt);if (distance > furthestDistance) {furthestDistance = distance;C = pt;}}hullmyPoints.push_back(C);for (const auto &pt : Sk) {if (myPointInTriangle(pt, P, C, Q)) {S0.push_back(pt);}else if (0 < SideOfLine(P, C, pt)) {S1.push_back(pt);}else if (0 < SideOfLine(C, Q, pt)) {S2.push_back(pt);}}FindHull(S1, P, C, hullmyPoints);FindHull(S2, C, Q, hullmyPoints);
}// http://www.cse.yorku.ca/~aaw/Hang/quick_hull/Algorithm.html
void QuickHull(const std::vector<myPoint> &s, std::vector<myPoint> &hullmyPoints) {myPoint A = s[0];myPoint B = s[s.size() - 1];hullmyPoints.push_back(A);hullmyPoints.push_back(B);std::vector<myPoint> S1;std::vector<myPoint> S2;for (auto it = s.begin() + 1; it != s.end() - 1; ++it) {const myPoint pt = *it;const int s1 = SideOfLine(A, B, pt);const int s2 = SideOfLine(B, A, pt);if (0 < s1) {S1.push_back(pt);}else if (0 < s2) {S2.push_back(pt);}}FindHull(S1, A, B, hullmyPoints);FindHull(S2, B, A, hullmyPoints);
}Mat mypredone(IplImage* srcipl, vector<Mat> bgrimgs)
{预处理Mat img(srcipl, 0);split(img, bgrimgs);Mat bimg(img.size(), CV_8UC1, cv::Scalar(0));bgrimgs[0].copyTo(bimg);threshold(bimg, bimg, 10, 255, CV_THRESH_BINARY/*|CV_THRESH_OTSU*/);Mat element(4, 4, CV_8U, cv::Scalar(1));morphologyEx(bimg, bimg, cv::MORPH_OPEN, element);//for (int i = 0; i < 20; i++)//{// uchar* data = bimg.ptr<uchar>(i);//  for (int j = 0; j < bimg.size().width; j++)//     data[j] = 0;//}//for (int i = bimg.size().height - 19; i < bimg.size().height; i++)//{// uchar* data = bimg.ptr<uchar>(i);//  for (int j = 0; j < bimg.size().width; j++)//     data[j] = 0;//}return bimg;
}
//背面quickhull   去除溜槽走光点等噪声
IplImage* luobin_backcontour(Mat bimg)
{IplImage mybimgipl = bimg;CvMemStorage *storage = cvCreateMemStorage();CvSeq *contour = NULL, *hull = NULL;vector<CvPoint> allpoints;vector<myPoint> myallpoints;CvContourScanner scanner = cvStartFindContours(&mybimgipl, storage);while ((contour = cvFindNextContour(scanner)) != NULL){/去掉溜槽走光点的 想法CvMoments *moments = (CvMoments*)malloc(sizeof(CvMoments));cvMoments(contour, moments, 1);double moment10 = cvGetSpatialMoment(moments, 1, 0);double moment01 = cvGetSpatialMoment(moments, 0, 1);double area = cvGetSpatialMoment(moments, 0, 0);double posX = moment10 / area;double posY = moment01 / area;double mylenth = cvArcLength(contour);double myarea = cvContourArea(contour);//cout << "length=" << mylenth << "   area=" << myarea << " 重心: " << "(" << posX << " , " << posY << ")" << " " << endl;//center lightif (posX > double(236.0) && posX<double(243.0) && posY>double(171.0) && posY<double(197.0) && myarea<double(141) && mylenth < double(71)){cvSubstituteContour(scanner, NULL);continue;}//right lightif (posX > double(384.0) && posX<double(395.0) && posY>double(90.0) && posY<double(113.0) && myarea<double(316) && mylenth < double(90)){cvSubstituteContour(scanner, NULL);continue;}//belowif (posX >160.0 && posX<331.0 && posY>295.0 && posY < 362.0 && myarea < 170 && mylenth < 100){cvSubstituteContour(scanner, NULL);continue;}if (posX >212.0 && posX<251.0 && posY>248.0 && posY < 269.0 && myarea < 21 && mylenth < 20){cvSubstituteContour(scanner, NULL);continue;}if (posX >256.0 && posX<271.0 && posY>296.0 && posY < 299.5 && myarea < 25 && mylenth < 20){cvSubstituteContour(scanner, NULL);continue;}if (posX >210.0 && posX<215.0 && posY>350.0 && posY < 358.0 && myarea < 250 && mylenth < 100){cvSubstituteContour(scanner, NULL);continue;}// special if (myarea == 0){cvSubstituteContour(scanner, NULL);continue;}///hull = cvConvexHull2(contour, 0, CV_CLOCKWISE, 0);CvPoint pt0 = **(CvPoint**)cvGetSeqElem(hull, hull->total - 1);myPoint mypt0;mypt0.x = (float)pt0.x;mypt0.y = (float)pt0.y;allpoints.push_back(pt0);myallpoints.push_back(mypt0);for (int i = 0; i < hull->total; ++i){CvPoint pt1 = **(CvPoint**)cvGetSeqElem(hull, i);allpoints.push_back(pt1);myPoint mypt1;mypt1.x = (float)pt1.x;mypt1.y = (float)pt1.y;myallpoints.push_back(mypt1);}}std::sort(myallpoints.begin(), myallpoints.end());std::vector<myPoint> myhullPoints;QuickHull(myallpoints, myhullPoints);CvSeq *hull2 = NULL;CvSeq* ptseq = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2, sizeof(CvContour), sizeof(CvPoint), storage);for (int i = 0; i < myhullPoints.size(); ++i){myPoint pt1 = myhullPoints[i];CvPoint myfinalpot1;myfinalpot1.x = pt1.x;myfinalpot1.y = pt1.y;cvSeqPush(ptseq, &myfinalpot1);}hull2 = cvConvexHull2(ptseq, 0, CV_CLOCKWISE, 1);IplImage *mydst3 = cvCreateImage(cvGetSize(&mybimgipl), 8, 1);cvZero(mydst3);cvDrawContours(mydst3, hull2, CV_RGB(255, 255, 255), CV_RGB(255, 255, 255), -1, CV_FILLED, 8);return mydst3;
}//正面quickhull
IplImage* luobin_frontcontour(Mat bimg)
{IplImage mybimgipl = bimg;CvMemStorage *storage = cvCreateMemStorage();CvSeq *contour = NULL, *hull = NULL;vector<CvPoint> allpoints;vector<myPoint> myallpoints;CvContourScanner scanner = cvStartFindContours(&mybimgipl, storage);while ((contour = cvFindNextContour(scanner)) != NULL){hull = cvConvexHull2(contour, 0, CV_CLOCKWISE, 0);CvPoint pt0 = **(CvPoint**)cvGetSeqElem(hull, hull->total - 1);myPoint mypt0;mypt0.x = (float)pt0.x;mypt0.y = (float)pt0.y;allpoints.push_back(pt0);myallpoints.push_back(mypt0);for (int i = 0; i < hull->total; ++i){CvPoint pt1 = **(CvPoint**)cvGetSeqElem(hull, i);allpoints.push_back(pt1);myPoint mypt1;mypt1.x = (float)pt1.x;mypt1.y = (float)pt1.y;myallpoints.push_back(mypt1);}}std::sort(myallpoints.begin(), myallpoints.end());std::vector<myPoint> myhullPoints;QuickHull(myallpoints, myhullPoints);CvSeq *hull2 = NULL;CvSeq* ptseq = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2, sizeof(CvContour), sizeof(CvPoint), storage);for (int i = 0; i < myhullPoints.size(); ++i){myPoint pt1 = myhullPoints[i];CvPoint myfinalpot1;myfinalpot1.x = pt1.x;myfinalpot1.y = pt1.y;cvSeqPush(ptseq, &myfinalpot1);}hull2 = cvConvexHull2(ptseq, 0, CV_CLOCKWISE, 1);IplImage *mydst3 = cvCreateImage(cvGetSize(&mybimgipl), 8, 1);cvZero(mydst3);cvDrawContours(mydst3, hull2, CV_RGB(255, 255, 255), CV_RGB(255, 255, 255), -1, CV_FILLED, 8);return mydst3;
}char filename[100];
char newcontour[100];
char grayimg[100];
char myback[100];
char contrast[100];void main()
{TickMeter tm;tm.start();for (int i = 1; i <= 1337; i++){//背面找轮廓sprintf(filename, "背面图\\%d.bmp", i);sprintf(newcontour, "罗彬背面轮廓3\\%d.bmp", i);IplImage* src_ipl = cvLoadImage(filename);vector<Mat> bgrimgs;Mat bimg = mypredone(src_ipl, bgrimgs);IplImage* luobin_result = luobin_backcontour(bimg);cvSaveImage(newcontour, luobin_result);正面找轮廓sprintf(filename, "正面图\\%d.bmp", i);sprintf(newcontour, "罗彬正面轮廓\\%d.bmp", i);IplImage* src_ipl = cvLoadImage(filename);vector<Mat> bgrimgs;Mat bimg = mypredone(src_ipl, bgrimgs);IplImage* luobin_result = luobin_frontcontour(bimg);}tm.stop();cout << "count=" << tm.getCounter() << ",process time=" << tm.getTimeMilli() << endl;
}

这样就行了!

将多个凸包连接起来形成一个大凸包找到最接近的轮廓相关推荐

  1. python连接mysql查询一个数据_使用Connector / Python连接MySQL/查询数据

    使用Connector / Python连接MySQL connect()构造函数创建到MySQL服务器的连接并返回一个 MySQLConnection对象 在python中有以下几种方法可以连接到M ...

  2. mysql 列连接_mysql – 将一个表中的多个列连接到另一个...

    我正在尝试学习如何将一个表中的多个列连接到另一个表中的单个列. 这是我最简单形式的表结构: 球队 id | team_name | 1 | teamA | 2 | teamB | 3 | teamC ...

  3. Linux命令:netstat【监控TCP/IP网络,可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息】【TCP的11种状态】

    netstat命令是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表.实际的网络连接以及每一个网络接口设备的状态信息. netstat [选项] 选项 描述 -a 显示所有网络连接和监听的所 ...

  4. SSH框架连接Oracle的一个简单项目

    SSH框架连接Oracle的一个简单项目 项目准备 知识准备 软件 实操 代码 页面展示 遇到的问题 项目准备 知识准备 下面是我一个新手对于本次项目的了解: 我们是使用spring整合struts2 ...

  5. 亚马逊AWS学习——多网络接口下配置EC2实例连接公网的一个“bug”

    转载请注明出处:http://blog.csdn.net/dongdong9223/article/details/47667627 本文出自[我是干勾鱼的博客] 之前在<亚马逊AWS学习--E ...

  6. 下一个大计算平台? Amazon Echo 研发幕后全揭露

    作为亚马逊打入智能家居并占据入口地位的标志产品,Echo的研发历程一波三折.本文记者采访内部一线人员,得到Echo问世幕后消息:亚马逊最初瞄准AR,不成后转做声控扬声器,Fire Phone的失败让这 ...

  7. 内连接,外链接(左连接、右连接、全连接),交叉连接大总结

    转载自 内连接,外链接(左连接.右连接.全连接),交叉连接大总结 1.什么是连接查询呢? 概念:根据两个表或多个表的列之间的关系,从这些表中查询数据. 目的:实现多个表查询操作. 2.分类: 首先划分 ...

  8. 个是云计算,一个大数据,一个人工智能,

    我今天要讲这三个话题,一个是云计算,一个大数据,一个人工智能,我为什么要讲这三个东西呢?因为这三个东西现在非常非常的火,它们之间好像互相有关系,一般谈云计算的时候也会提到大数据,谈人工智能的时候也会提 ...

  9. 索爱SA-K37拉杆音箱,随时随地帮你撑起一个大舞台

    你是我的小呀小苹果儿,怎么爱你都不嫌多,红红的小脸儿温暖我的心窝,点亮我生命的火火火火火火-摘下星星送给你,拽下月亮送给你,让太阳每天为你升起--每日清晨.傍晚,每每响起类似这样的旋律,我们就会看到广 ...

最新文章

  1. 在C#中怎样推断线程当前所处的状态
  2. php模块介绍,Python模块介绍
  3. 验证数字的正则表达式集
  4. 【原理+实战+视频+源码】手撸SpringBoot缓存系统
  5. php获取ios或android通过文件头(header)传过来的坐标,通过百度接口获取具体城市和地址,并存入到session中...
  6. android xml png,android - 使用.png文件中的形状创建xml聊天气泡 - 堆栈内存溢出
  7. centos 7配置firewall防火墙的地址伪装和端口转发实例
  8. 《PowerShell V3——SQL Server 2012数据库自动化运维权威指南》——1.5 安装SMO
  9. android 的webview解析
  10. 排序和去重--说说两个简单常用的算法
  11. app 图标规格参考表
  12. 虚拟机安装centos
  13. Spring-第2天
  14. HMM学习(2)-Generating Patterns
  15. php arraymap 匿名函数,结合代码详细为你讲解,php中的array_map,array_walk以及匿名函数...
  16. 共空间模式算法(CSP)
  17. 前端实时可视化工具livereload安装和使用
  18. 【ATSC】韩国:2017年将迎来ATSC3.0广播时代
  19. mysql 节假日判断_sql 节假日判断(春节、中秋、国庆、周末等)
  20. html 字符画,字符画

热门文章

  1. 【JavaWeb】表单标签案例CSS(24)
  2. 字典树与01字典树详解
  3. git cz 规范化提交
  4. win10系统日期和服务器日期不一致,windows 10 系统时间显示不一致问题
  5. Java读取文件的内容到String字符串中
  6. eclipse打开新工作空间,个人偏好设置问题
  7. oracle sql列转行_oracle 列转行
  8. Steam无法载入网页 - 解决方案
  9. 第n个斐波那契数(C语言)
  10. 微信js调用摄像头拍照上传_微信JSSDK实现打开摄像头拍照再将相片保存到服务器...