├── 5.png ├── README.md ├── demo.cpp ├── twoPass.cpp └── twoPass.h /5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polyGithub/opencv_twoPass/13feff495705ce3f4031424bb497cdcacea1c3a6/5.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # opencv_twoPass 2 | 图像目标检测识别,计算物体个数,针对电子元器件计算.主要是利用连通区域发现算法,发现所有连通区域,获取最小部分的连通区域集合(图片预处理很关键),根据此连通区域面积, 作为单个器件大小,从而求取出粘连部分的个数,完成对整个元器件的计算,准备率相当的高,目测可达99%以上 3 | 4 | 5 | 6 | 代码编译 7 | 8 | g++ demo.cpp twoPass.cpp -o test `pkg-config --cflags --libs opencv` 9 | 10 | 运行 11 | 12 | ./test 5.png 13 | -------------------------------------------------------------------------------- /demo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "twoPass.h" 7 | #include 8 | using namespace std; 9 | using namespace cv; 10 | 11 | cv::Scalar getRandomColor() 12 | { 13 | uchar r = 255 * (rand() / (1.0 + RAND_MAX)); 14 | uchar g = 255 * (rand() / (1.0 + RAND_MAX)); 15 | uchar b = 255 * (rand() / (1.0 + RAND_MAX)); 16 | return cv::Scalar(b, g, r); 17 | } 18 | 19 | cv::Mat showColorLabel(cv::Mat label) 20 | { 21 | int imgW = label.cols; 22 | int imgH = label.rows; 23 | std::map colors; 24 | 25 | cv::Mat colorLabel = cv::Mat::zeros(imgH, imgW, CV_8UC3); 26 | int *pLabel = (int*)label.data; 27 | uchar *pColorLabel = colorLabel.data; 28 | for (int i = 0; i < imgH; i++) 29 | { 30 | //printf("\n"); 31 | for (int j = 0; j < imgW; j++) 32 | { 33 | int idx = (i*imgW + j) * 3; 34 | int pixelValue = pLabel[i*imgW + j]; 35 | //printf(" %02x",pixelValue); 36 | if (pixelValue > 0) 37 | { 38 | if (colors.count(pixelValue) <= 0) 39 | { 40 | colors[pixelValue] = getRandomColor(); 41 | } 42 | cv::Scalar color = colors[pixelValue]; 43 | pColorLabel[idx + 0] = color[0]; 44 | pColorLabel[idx + 1] = color[1]; 45 | pColorLabel[idx + 2] = color[2]; 46 | } 47 | } 48 | } 49 | 50 | return colorLabel; 51 | } 52 | 53 | int main(int argc, char *argv[]) 54 | { 55 | string imageName = argv[1]; 56 | cv::Mat srcImage = cv::imread(imageName, 1); 57 | if (!srcImage.data ) 58 | { 59 | cout << "No image data" << endl; 60 | return 0; 61 | } 62 | cv::Mat image; 63 | cv::cvtColor(srcImage, image, CV_RGB2GRAY); 64 | 65 | cv::Mat threshImg; 66 | cv::threshold(image, threshImg, 140, 255, cv::THRESH_BINARY); 67 | cv::bitwise_not(threshImg, threshImg); 68 | 69 | cv::imshow("threshImg", threshImg); 70 | 71 | Mat element = getStructuringElement(MORPH_RECT,Size(3,3)); 72 | Mat destImage; 73 | erode(threshImg,destImage,element); 74 | cv::imshow("destImage", destImage); 75 | 76 | element = getStructuringElement(MORPH_RECT,Size(5,5)); 77 | dilate( destImage, destImage, element ); 78 | 79 | cv::Mat labelImg=cv::Mat::zeros(image.size(), CV_32SC1); 80 | int maxLabel = -1; 81 | TwoPass twoPassMethod(destImage.cols*destImage.rows); 82 | twoPassMethod.run(destImage, labelImg, maxLabel); 83 | 84 | cv::imshow("labelImg", labelImg * 60); 85 | cv::Mat colorLabelImg = showColorLabel(labelImg); 86 | 87 | cv::imshow("colorLabel", colorLabelImg); 88 | 89 | vector< vector > contours; 90 | 91 | findContours(destImage,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE); 92 | drawContours(destImage,contours,-1,cv::Scalar(128),1); 93 | imshow("dilate",destImage); 94 | 95 | cout< 1 ) 114 | { 115 | Rect r0=boundingRect(contours[i]); 116 | rectangle(srcImage,r0,cv::Scalar(0, 0, 255),1); 117 | sprintf(snum,"%d",k); 118 | putText(srcImage, snum, Point(r0.x, r0.y), FONT_HERSHEY_SIMPLEX, 1, Scalar(0,0,255), 1, 1); 119 | } 120 | } 121 | char str[10] = {0}; 122 | char * num = str; 123 | sprintf(num,"%d",n); 124 | putText(srcImage, num, Point(50, 50), FONT_HERSHEY_SIMPLEX, 1, Scalar(0,255,0), 2, 2); 125 | cv::imshow("result", srcImage); 126 | cv::waitKey(0); 127 | } 128 | -------------------------------------------------------------------------------- /twoPass.cpp: -------------------------------------------------------------------------------- 1 | #include "twoPass.h" 2 | 3 | TwoPass::TwoPass(int size) 4 | { 5 | int maxSize = size; 6 | parent = (int*)malloc(maxSize * sizeof(int)); 7 | memset(parent, 0, maxSize); 8 | } 9 | 10 | TwoPass::~TwoPass() 11 | { 12 | free(parent); 13 | } 14 | 15 | // find the root of label x 16 | int TwoPass::Find(int x, int parent[]) 17 | { 18 | //assert(x < maxSize); 19 | int i = x; 20 | while (0 != parent[i]) 21 | i = parent[i]; 22 | //cout << "i " << i <(y, x) != 0) 55 | { 56 | //left and up labels 57 | int left = (x - 1 < 0) ? 0 : dst.at(y, x - 1); 58 | int up = (y - 1 < 0) ? 0 : dst.at(y - 1, x); 59 | //at least one label is marked 60 | if (left != 0 || up != 0) 61 | { 62 | //two labels are marked 63 | if (left != 0 && up != 0) 64 | { 65 | //adopt smaller label 66 | dst.at(y, x) = min(left, up); 67 | if (left <= up) 68 | Union(up, left, parent); 69 | else if (up(y, x) = max(left, up); 76 | } 77 | } 78 | else 79 | { 80 | //non of two labels is markded, so add a new label 81 | dst.at(y, x) = ++label; 82 | } 83 | } 84 | } 85 | } 86 | 87 | //second pass 88 | for (int y = 0; y < imgH; y++) 89 | { 90 | //printf("\n"); 91 | for (int x = 0; x < imgW; x++) 92 | { 93 | if (binaryImg.at(y, x) != 0) 94 | dst.at(y, x) = Find(dst.at(y, x), parent); 95 | // printf("%d ",dst.at(y, x)); 96 | } 97 | } 98 | } 99 | 100 | //find the max label value 101 | void TwoPass::findMaxLabel(cv::Mat labelImg, int &max) 102 | { 103 | int imgH = labelImg.rows; 104 | int imgW = labelImg.cols; 105 | int *pLabel = (int*)labelImg.data; 106 | 107 | for (int i = 0; i < imgH; i++) 108 | { 109 | for (int j = 0; j < imgW; j++) 110 | { 111 | int idx = i*imgW + j; 112 | if (pLabel[idx] > max) max = pLabel[idx]; 113 | } 114 | } 115 | } 116 | 117 | void TwoPass::run(const cv::Mat threshImg, cv::Mat &labelImg, int &max) 118 | { 119 | //detect connected-region using two Pass method 120 | twoPassConnectComponent(threshImg, labelImg); 121 | 122 | //find the largest label 123 | findMaxLabel(labelImg, max); 124 | //printf("max=%d\n",max); 125 | 126 | 127 | cout << "max " << max < 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | class TwoPass 10 | { 11 | public: 12 | TwoPass(int size); 13 | ~TwoPass(); 14 | 15 | private: 16 | int maxSize; 17 | int *parent; 18 | 19 | private: 20 | int Find(int x, int parent[]); 21 | void Union(int x, int y, int parent[]); 22 | void twoPassConnectComponent(cv::Mat binaryImg, cv::Mat &dstImg); 23 | void findMaxLabel(cv::Mat labelImg, int & max); 24 | 25 | public: 26 | void run(const cv::Mat img, cv::Mat &labelImg, int &max); 27 | 28 | }; 29 | --------------------------------------------------------------------------------