透气膜项目代码
#include <iostream>
#include "badDetect.h"
using namespace std;
//測試的主函數(shù)
int main()
{
?? ?PreParams params;//定義預(yù)設(shè)置參數(shù)的結(jié)構(gòu)體
?? ?Mat img = imread("D:\\測試結(jié)果圖片\\1.bmp",0);
?? ?Mat img1 = imread("D:\\測試結(jié)果圖片\\2.bmp",0);
?? ?/*Mat img = imread("樣品圖4\\4.bmp",0);
?? ?Mat img1 = imread("兩面打光圖\\壓印\\2.bmp",0);*/
?? ?char* imgData = (char*)img.data;
?? ?char* imgData1 = (char*)img1.data;
?? ?int height = img.rows;
?? ?int width = img.cols;
?? ?int result[4][10] = {0};
?? ?int detectError[4] = {0};
?? ?//進(jìn)行參數(shù)設(shè)置
?? ?params.rubDetectParams.holeNum = 1;?? ??? ??? ??? ?//樣本穿洞數(shù)
?? ?params.memBwArea = 250;?? ??? ??? ??? ??? ??? ??? ?//膜內(nèi)黑白點(diǎn)與膜皺面積分界值
?? ?params.rubDetectParams.memOffset = 14;?? ??? ??? ?//膜最大偏移值,偏心檢測
?? ?params.rubDetectParams.memUdOffset = 26;?? ??? ?//膜上下偏心閾值
?? ?params.memPixelDif = 17;?? ??? ??? ??? ??? ??? ?//膜內(nèi)最大像素差,黑白點(diǎn)、膜皺檢測
?? ?params.rubDetectParams.memRubDist = 245;?? ??? ?//膜與膠的左/右標(biāo)準(zhǔn)距離
?? ?params.sampleNum = 4;?? ??? ??? ??? ??? ??? ??? ?//一張圖中的樣本數(shù)
?? ?params.slikThreold = 8;?? ??? ??? ??? ??? ??? ??? ?//毛絲閾值
?? ?params.rubDetectParams.rubPixelArea = 70;?? ??? ?//膠上最小臟點(diǎn)面積
?? ?params.rubDetectParams.rubPixelDif = 50;?? ??? ?//膠上臟點(diǎn)最小像素差
?? ?params.minBwArea = 50;?? ??? ??? ??? ??? ??? ??? ?//膜內(nèi)黑白點(diǎn)最小面積
?? ?params.hole = 2;?? ??? ??? ??? ??? ??? ??? ??? ?//缺孔檢測
?? ?params.levcover = 16;?? ??? ??? ??? ??? ??? ??? ?//左右移位檢測閾值
?? ?params.udLeave = 16;?? ??? ??? ??? ??? ??? ??? ?//上下移位閾值
?? ?params.bwDist = 7;?? ??? ??? ??? ??? ??? ??? ??? ?//黑點(diǎn)離邊緣距離
?? ?params.rubDetectParams.rubThreold = 80;?? ??? ??? ?//膠上臟點(diǎn)閾值
?? ?params.fpArea = 350;
?? ?
?? ?double t = (double)getTickCount();
?? ?badDetect(imgData,imgData1,height,width,params,result,detectError);?? ??? ?//進(jìn)行檢測
?? ?t = ((double)getTickCount() - t)/getTickFrequency();
?? ?cout<<"耗時(shí):"<<t<<endl;
?? ?for(int i = 0;i<4;i++)
?? ?{
?? ??? ?cout<<"錯(cuò)誤碼:"<<detectError[i]<<endl;
?? ??? ?cout<<"result"<<i+1<<": ";
?? ??? ?for(int j = 0;j<10;j++)
?? ??? ?{
?? ??? ??? ?cout<<result[i][j]<<" ?";
?? ??? ?}
?? ??? ?cout<<"\n";
?? ?}
?? ?namedWindow("change",0);
?? ?imshow("change",img);
?? ?waitKey(0);
?? ?namedWindow("change1",0);
?? ?imshow("change1",img1);
?? ?waitKey(0);
?? ?cin.get();
?? ?return 0;
}
//總接口函數(shù)
void badDetect(char* img,char* img1,int imgWidth,int imgHeight,const PreParams params,int result[][10],int detectError[])
{
?? ?vector<Mat> roiImgs;
?? ?vector<Mat> MG;
?? ?vector<Mat> dstImg;
?? ?RubDetectParams rubParams;
?? ?dst_width = imgWidth;
?? ?dst_height = imgHeight;
?? ?int roi_num = params.sampleNum;//提取的感興趣區(qū)域數(shù)量
?? ?int minMemBwArea = params.memBwArea;//膜內(nèi)允許的像素偏差面積?? ?
?? ?int slikThreold = params.slikThreold;//毛絲離輪廓距離,用于檢測毛絲
?? ?int pianxin = params.rubDetectParams.memOffset;//偏心檢測
?? ?int memRubDist = params.rubDetectParams.memRubDist;//膜離左右的標(biāo)準(zhǔn)距離,偏心檢測
?? ?int memOffset = params.memPixelDif;//膜內(nèi)允許的像素偏差
?? ?int minBwArea = params.minBwArea; // 膜內(nèi)黑白點(diǎn)最小面積
?? ?int hole = params.hole;?? ??? ??? ?//缺孔檢測數(shù)據(jù)
?? ?int levcover = params.levcover;?? ?//移位檢測閾值
?? ?int udLeave ?= params.udLeave;
?? ?int sampleNum = params.sampleNum;?? ?//移位檢測閾值
?? ?int memUdOffset = params.rubDetectParams.memUdOffset;
?? ?int bwdist = params.bwDist;
?? ?int rubThreold = params.rubDetectParams.rubThreold;
?? ?int fpArea = params.fpArea;
?? ?rubParams.holeNum = params.rubDetectParams.holeNum;
?? ?rubParams.memOffset = params.rubDetectParams.memOffset;
?? ?rubParams.memRubDist = params.rubDetectParams.memRubDist;
?? ?rubParams.minSampleArea = params.rubDetectParams.minSampleArea;
?? ?rubParams.rubPixelArea = params.rubDetectParams.rubPixelArea;
?? ?rubParams.rubPixelDif = params.rubDetectParams.rubPixelDif;
?? ?rubParams.rubThreold = params.rubDetectParams.rubThreold;
?? ?Mat pSrcImg(Size(imgHeight,imgWidth),CV_8UC1,img);
?? ?Mat pSrcImg1(Size(imgHeight,imgWidth),CV_8UC1,img1);
?? ?Mat srcImg,srcImg1;
?? ?pSrcImg.copyTo(srcImg);
?? ?pSrcImg1.copyTo(srcImg1);
?? ?
?? ?if(!(srcImg.data && srcImg1.data))
?? ?{
?? ??? ?for(int i = 0;i < 4;i++)
?? ??? ?{
?? ??? ??? ?for(int j = 0;j<10;j++)
?? ??? ??? ?{
?? ??? ??? ??? ?result[i][j] = -1;//兩張圖中任意一張為空
?? ??? ??? ?}
?? ??? ?}
?? ??? ?for(int i = 0;i < 4;i++)
?? ??? ?{
?? ??? ??? ?detectError[i] = -1;
?? ??? ?}
?? ??? ?return;
?? ?}
?? ?int flag = getRoiImg(srcImg,sampleNum,dstImg,result);
?? ?if(flag == -1)
?? ?{
?? ??? ?for(int i = 0;i < 4;i++)
?? ??? ?{
?? ??? ??? ?detectError[i] = -2;
?? ??? ?}
?? ??? ?return;
?? ?}
?? ?//showImg(dstImg);
?? ?Mat roi1 = srcImg(Rect(0,0,srcImg.cols/2,srcImg.rows/2));
?? ?Mat roi2 = srcImg(Rect(srcImg.cols/2,0,srcImg.cols/2,srcImg.rows/2));
?? ?Mat roi3 = srcImg(Rect(0,srcImg.rows/2,srcImg.cols/2,srcImg.rows/2));
?? ?Mat roi4 = srcImg(Rect(srcImg.cols/2,srcImg.rows/2,srcImg.cols/2,srcImg.rows/2));
?? ?Mat mianguang1 = srcImg1(Rect(0,0,srcImg.cols/2,srcImg.rows/2));
?? ?Mat mianguang2 = srcImg1(Rect(srcImg.cols/2,0,srcImg.cols/2,srcImg.rows/2));
?? ?Mat mianguang3 = srcImg1(Rect(0,srcImg.rows/2,srcImg.cols/2,srcImg.rows/2));
?? ?Mat mianguang4 = srcImg1(Rect(srcImg.cols/2,srcImg.rows/2,srcImg.cols/2,srcImg.rows/2));
?? ?roiImgs.push_back(roi1);
?? ?roiImgs.push_back(roi2);
?? ?roiImgs.push_back(roi3);
?? ?roiImgs.push_back(roi4);
?? ?MG.push_back(mianguang1);
?? ?MG.push_back(mianguang2);
?? ?MG.push_back(mianguang3);
?? ?MG.push_back(mianguang4);
?? ?MemDetectResult memdr;//膜內(nèi)檢測結(jié)果傳回
?? ?vector<vector<Point>> badspots;//膠上壞點(diǎn)傳回
?? ?int leavCenter[3] = {0};//偏心結(jié)果傳回
?? ?vector<vector<Point2f>> roRect;
?? ?Point circlepoint[4] = {(0,0),(0,0),(0,0),(0,0)};//用于檢測偏心的圓心
?? ?vector<vector<Point>> T(4);
?? ?circleEdges = T;
//#pragma omp parallel for
?? ?for(int i = 0;i<roiImgs.size();i++)//循環(huán)檢測每一個(gè)樣本
?? ?{
?? ??? ?deError[i] = 0;
?? ??? ?int memres = centerMemDetect(roiImgs[i],i,&memdr,circlepoint,memOffset,minMemBwArea,slikThreold,minBwArea,result,bwdist,fpArea);//開始中心膜檢測
?? ??? ?if(result[i][0] == -1 || result[i][0] == -2 || result[i][0] == -3 || memres == -1)
?? ??? ?{
?? ??? ??? ?detectError[i] = deError[i];
?? ??? ??? ?continue;
?? ??? ?}
?? ??? ?int locres = localDetect(roiImgs[i],result,hole,i,levcover,udLeave,circlepoint);
?? ??? ?if(locres < 0)
?? ??? ?{
?? ??? ??? ?detectError[i] = deError[i];
?? ??? ??? ?continue;
?? ??? ?}
?? ??? ?int bads = badSpot(MG[i],badspots,circlepoint,leavCenter,rubParams,i,roRect,result);//開始外輪廓檢
?? ??? ?if(bads < 0)
?? ??? ?{
?? ??? ??? ?detectError[i] = deError[i];
?? ??? ??? ?continue;
?? ??? ?}
?? ??? ?int lackm = lackMaterial(result,dstImg[i],i);
?? ??? ?if(lackm < 0)
?? ??? ?{
?? ??? ??? ?detectError[i] = deError[i];
?? ??? ??? ?continue;
?? ??? ?}
?? ??? ?int centeroff = centerOffset(circlepoint[i],memRubDist,pianxin,memUdOffset,result,i);
?? ??? ?if(centeroff < 0)
?? ??? ?{
?? ??? ??? ?detectError[i] = deError[i];
?? ??? ??? ?continue;
?? ??? ?}
?? ??? ?detectError[i] = deError[i];
?? ??? ?
?? ?}
?? ?paintProcessedImg(img,img1,memdr,badspots,leavCenter,result,roRect);//畫出檢測結(jié)果
?? ?localEdges.clear();
?? ?circleEdges.clear();
?? ?/*mask_right.release();
?? ?mask_left.release();*/
?? ?//imwrite("D:\\bc1.bmp",pSrcImg);
?? ?//imwrite("D:\\bc2.bmp",pSrcImg1);
?? ?//namedWindow("change",0);
?? ?//imshow("change",srcImg);
?? ?//waitKey(0);
?? ?//namedWindow("change1",0);
?? ?//imshow("change1",srcImg1);
?? ?//waitKey(0);
?? ?/*char str1[10]={};
?? ?char str2[10] = {};
?? ?char str3[10] = {};
?? ?char str4[50] = {};
?? ?char str5[10] = {};
?? ?itoa(rubParams.holeNum,str1,10);
?? ?itoa(rubParams.memOffset,str2,10);
?? ?itoa(rubParams.memRubDist,str3,10);
?? ?itoa(rubParams.minSampleArea,str4,10);
?? ?itoa(rubParams.rubPixelArea,str5,10);
?? ?putText(srcImg1,str1,Point(100,100),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ?putText(srcImg1,str2,Point(150,100),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ?putText(srcImg1,str3,Point(200,100),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ?putText(srcImg1,str4,Point(250,100),CV_FONT_ITALIC,1,Scalar(0,0,0));?
?? ?putText(srcImg1,str5,Point(300,100),CV_FONT_ITALIC,1,Scalar(0,0,0));*/
}
//膜中心檢測函數(shù)
//memResult:結(jié)果存放結(jié)構(gòu)體
//minMenBwArea:最小黑點(diǎn)白點(diǎn)面積
int centerMemDetect(const Mat srcImg,int imgIndex, MemDetectResult* memResult,Point circlepoint[],int memOffset,int minMemBwArea,int slikThreold,int memBwArea,int result[][10],int bwdist,int fpArea)
{
?? ?int addX = 0;
?? ?int addY = 0;
?? ?if(imgIndex == 1)
?? ?{
?? ??? ?addX = dst_height/2;
?? ?}
?? ?if(imgIndex == 2)
?? ?{
?? ??? ?addY = dst_width/2;
?? ?}
?? ?if(imgIndex == 3)
?? ?{
?? ??? ?addX = dst_height/2;
?? ??? ?addY = dst_width/2;
?? ?}
?? ?Mat img,gray,bw;
?? ?srcImg.copyTo(img);
?? ?if(img.channels() == 3)
?? ??? ?cvtColor(srcImg,gray,CV_RGB2GRAY);
?? ?else
?? ??? ?gray = img;
?? ?double rubPixel_level[256] = {0};
?? ?double rubAvePixel = 0.0;
?? ?double rubPixelNum = 0.0;
?? ?double rubPixelSum = 0.0;
?? ?for(int i = 0;i<gray.rows;i++)
?? ?{
?? ??? ?uchar* data = gray.ptr<uchar>(i);
?? ??? ?for(int j = 0;j<gray.cols;j++)
?? ??? ?{
?? ??? ??? ?int temp = data[j];
?? ??? ??? ?rubPixel_level[temp]++;
?? ??? ?}
?? ?}
?? ?for(int i = 0;i<30;i++)
?? ?{
?? ??? ?if(rubPixel_level[i]>1000)
?? ??? ?{
?? ??? ??? ?rubPixelNum = rubPixelNum + rubPixel_level[i]*i;
?? ??? ??? ?rubPixelSum = rubPixelSum + rubPixel_level[i];
?? ??? ?}
?? ?}
?? ?rubAvePixel = rubPixelNum/rubPixelSum;
?? ?int memThreold = 50;?? ?//提取中心膜時(shí)二值化閾值
?? ?int threold_low = rubAvePixel+7;?? ?//低閾值與高閾值區(qū)分復(fù)
?? ?int slikthreold = rubAvePixel+11;
?? ?int threold_high = threold_low+15; ?//低閾值與高閾值區(qū)分復(fù)偏
?? ?//--------------------提取出中心膜-----------------------------//
?? ?threshold(gray,bw,memThreold,255,CV_THRESH_BINARY);
?? ?GaussianBlur(bw,bw,Size(5,5),2,2);?
?? ?/*imshow("houfu",bw);
?? ?waitKey(0);*/
?? ?Mat bwcon;
?? ?bw.copyTo(bwcon);
?? ?vector<vector<Point>> cirConCount;
?? ?vector<Vec4i> cirHierarchy;
?? ?findContours(bwcon,cirConCount,cirHierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE);
?? ?if(cirConCount.size()>20)
?? ?{
?? ??? ?for(int i = 0;i<10;i++)
?? ??? ?{
?? ??? ??? ?result[imgIndex][i] = -3;//沒有檢測到圓,無樣本,返回-1
?? ??? ?}
?? ??? ?deError[imgIndex] = 1;
?? ??? ?return -1;
?? ?}
?? ?vector<Vec3f> hough_circles;
?? ?//霍夫圓變換粗定位圓,累加器為原圖像2/3,最小圓心距離5,canny高閾值,圓檢測閾值60,越小越能檢測到不規(guī)則的圓
?? ?HoughCircles(bw,hough_circles,CV_HOUGH_GRADIENT,1.5,5,200,100,50,0);
?? ?if(hough_circles.empty())
?? ?{
?? ??? ?for(int i = 0;i<10;i++)
?? ??? ?{
?? ??? ??? ?result[imgIndex][i] = -4;//沒有檢測到圓,無樣本,返回-1
?? ??? ?}
?? ??? ?deError[imgIndex] = 2;
?? ??? ?return -1;
?? ?}
?? ?for(int i = 0;i<hough_circles.size();i++)
?? ?{
?? ??? ?Point center((int)(hough_circles[i][0]),(int)(hough_circles[i][1]));
?? ??? ?int radius = (int)(hough_circles[i][2]);
?? ?}
?? ?int maxCircle = -1;//找出合適大小的圓
?? ?for(int i = 0;i<hough_circles.size();i++)
?? ?{
?? ??? ?if(hough_circles[i][2] < 140 && hough_circles[i][2]>100)
?? ??? ?{
?? ??? ??? ?maxCircle = i;
?? ??? ?}
?? ?}
?? ?int R;//霍夫變換產(chǎn)生的圓半徑
?? ?Mat roi,roiblur,roi_bw_low,roi_bw_high,edges;
?? ?double roi_centerX,roi_centerY,roi_radius;//最小二乘法擬合出的圓半徑和圓心
?? ?vector<Point> edges_point;
?? ?vector<vector<Point>> edges_contour;
?? ?vector<Vec4i> edges_hieratchy;
?? ?Point center;
?? ?int addroi = 37;
?? ?if(maxCircle != -1)
?? ?{
?? ??? ?center.x = (int)(hough_circles[maxCircle][0]);
?? ??? ?center.y = (int)(hough_circles[maxCircle][1]);
?? ??? ?R = (int)(hough_circles[maxCircle][2]);
?? ??? ?int x = center.x-R-addroi;
?? ??? ?int y = center.y-R-addroi;
?? ??? ?int width = 2*(R+addroi);
?? ??? ?if(x<0 || y<0 || (x+width)>img.cols || (y+width)>img.rows)
?? ??? ?{
?? ??? ??? ?for(int i = 0;i<10;i++)
?? ??? ??? ?{
?? ??? ??? ??? ?result[imgIndex][i] = -5;//沒有檢測到圓,無樣本,返回-1
?? ??? ??? ?}
?? ??? ??? ?deError[imgIndex] = 3;
?? ??? ??? ?return -1;
?? ??? ?}
?? ??? ?Rect roi_rect = Rect(x,y,width,width);
?? ??? ?roi = gray(roi_rect);
?? ??? ?medianBlur(roi,roiblur,3);
?? ??? ?medianBlur(roi,roi,3);
?? ??? ?threshold(roi,roi_bw_low,slikthreold,255,CV_THRESH_BINARY);
?? ??? ?Canny(roi_bw_low,edges,100,200);
?? ??? ?findContours(edges,edges_contour,edges_hieratchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_NONE);
?? ??? ?if(edges_contour.size() == 0)
?? ??? ?{
?? ??? ??? ?for(int i = 0;i<10;i++)
?? ??? ??? ?{
?? ??? ??? ??? ?result[imgIndex][i] = -6;//沒有檢測到圓,無樣本,返回-1
?? ??? ??? ?}
?? ??? ??? ?deError[imgIndex] = 4;
?? ??? ??? ?return -1;
?? ??? ?}
?? ??? ?contourSort(edges_contour);
?? ??? ?edges_point = edges_contour[0];
?? ?}
?? ?else
?? ?{
?? ??? ?for(int i = 0;i<10;i++)
?? ??? ?{
?? ??? ??? ?result[imgIndex][i] = -7;//檢測到圓大小不合適,無樣本,返回-1
?? ??? ?}
?? ??? ?deError[imgIndex] = 5;
?? ??? ?return -1;
?? ?}
?? ?//最小二乘法計(jì)算圓心和半徑
?? ?if(edges.data)
?? ?{
?? ??? ?circleLeastFit(edges_point,roi_centerX,roi_centerY,roi_radius);
?? ??? ?circle(roi,Point(roi_centerX,roi_centerY),roi_radius,Scalar(255,255,255),1,8,0);
?? ??? ?circlepoint[imgIndex].x = roi_centerX + center.x - R -addroi;//精確圓心傳遞到后面檢測需要的方法
?? ??? ?circlepoint[imgIndex].y = roi_centerY + center.y - R -addroi;
?? ?}
?? ?imshow("擬合圓",roi);
?? ?waitKey(0);
?? ?
?? ?int pixel_level[256] = {0};
?? ?double avePixel = 0.0;
?? ?double pixelNum = 0.0;
?? ?double pixelSum = 0.0;
?? ?for(int i = 0;i<roi.rows;++i)
?? ?{
?? ??? ?uchar* data = roi.ptr<uchar>(i);
?? ??? ?for(int j = 0;j<roi.cols;++j)
?? ??? ?{
?? ??? ??? ?int temp = data[j];
?? ??? ??? ?pixel_level[temp]++;
?? ??? ?}
?? ?}
?? ?for(int i = 255;i>60;i--)
?? ?{
?? ??? ?if(pixel_level[i]>100)
?? ??? ?{
?? ??? ??? ?pixelSum = pixelSum + pixel_level[i]*i;
?? ??? ??? ?pixelNum = pixelNum + pixel_level[i];
?? ??? ?}
?? ?}
?? ?if(pixelNum < 35000)
?? ?{
?? ??? ?for(int i = 0;i<10;i++)
?? ??? ?{
?? ??? ??? ?result[imgIndex][i] = -8;//透氣膜移位,返回-1
?? ??? ?}
?? ??? ?deError[imgIndex] = 6;
?? ??? ?return -1;
?? ?}
?? ?avePixel = pixelSum/pixelNum; ?//背景像素值
?? ?if(avePixel > 240)
?? ?{
?? ??? ?for(int i = 0;i<10;i++)
?? ??? ?{
?? ??? ??? ?result[imgIndex][i] = -9;//無透氣膜,返回-3
?? ??? ?}
?? ??? ?deError[imgIndex] = 7;
?? ??? ?return -1;
?? ?}
?? ?//-------------毛絲檢測------------//
?? ?Mat slikbw,slikAdp,slikResult,slik_edges;
?? ?threshold(roi,slikbw,50,255,CV_THRESH_BINARY_INV);
?? ?adaptiveThreshold(roi,slikAdp,255,ADAPTIVE_THRESH_MEAN_C,THRESH_BINARY_INV,7,15);
?? ?//threshold(roi,slikbw,avePixel-memOffset,255,CV_THRESH_BINARY);
?? ?addWeighted(slikbw,1.0,slikAdp,1.0,0,slikResult);//統(tǒng)計(jì)兩次的結(jié)果
?? ?/*imshow("maosi",slikAdp);
?? ?waitKey(0);*/
?? ?/*imshow("guding",slikbw);
?? ?waitKey(0);
?? ?imshow("result",slikResult);
?? ?waitKey(0);*/
?? ?Canny(slikResult,slik_edges,100,200);
?? ?vector<vector<Point>> slik_contour;
?? ?vector<Vec4i> slik_hieratchy;
?? ?findContours(slik_edges,slik_contour,slik_hieratchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_NONE);
?? ?contourSort(slik_contour);
?? ?/*imshow("bianyuan",slik_edges);
?? ?waitKey(0);*/
?? ?for(int i = 0;i<slik_contour.size();i++)
?? ?{
?? ??? ?if(slik_contour[i].size()>10)
?? ??? ?{
?? ??? ??? ?for(int j = 0;j<slik_contour[i].size();j++)
?? ??? ??? ?{
?? ??? ??? ??? ?double x2 = (slik_contour[i][j].x-roi_centerX)*(slik_contour[i][j].x-roi_centerX);
?? ??? ??? ??? ?double y2 = (slik_contour[i][j].y-roi_centerY)*(slik_contour[i][j].y-roi_centerY);
?? ??? ??? ??? ?double dist = roi_radius - sqrt(x2+y2);
?? ??? ??? ??? ?if(dist>slikThreold && dist<slikThreold+10)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?int tempX = slik_contour[i][j].x + center.x - R -addroi+addX;
?? ??? ??? ??? ??? ?int tempY = slik_contour[i][j].y + center.y - R -addroi+addY;
?? ??? ??? ??? ??? ?memResult->slik.push_back(Point(tempX,tempY));
?? ??? ??? ??? ??? ?result[imgIndex][0] = 1;
?? ??? ??? ??? ?}?? ?
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?if(!circleEdges[imgIndex].empty())
?? ?{
?? ??? ?circleEdges[imgIndex].clear();
?? ?}
?? ?for(int i = 0;i<edges_point.size();i++)
?? ?{
?? ??? ?Point temp(edges_point[i].x + center.x - R -addroi,edges_point[i].y + center.y - R -addroi);
?? ??? ?circleEdges[imgIndex].push_back(temp);
?? ?}
?? ?//-------------------雙閾值找復(fù)偏---------------------//
?? ?Mat roi_rub_low;
?? ?threshold(roiblur,roi_rub_low,threold_low,255,CV_THRESH_BINARY);
?? ?threshold(roiblur,roi_bw_high,threold_high,255,CV_THRESH_BINARY);
?? ?Mat rubArea = Mat::zeros(roi_bw_low.size(),CV_8UC1);
?? ?Mat rub_edges,rubConImg;
?? ?absdiff(roi_bw_high,roi_bw_low,rubArea);
?? ?//rubArea = roi_bw_high - roi_bw_low;
?? ?/*imshow("復(fù)偏",rubArea);
?? ?waitKey(0);*/
?? ?/*for(int i = 0;i<roi_rub_low.rows;i++)
?? ?{
?? ??? ?for(int j = 0;j<roi_rub_low.cols;j++)
?? ??? ?{
?? ??? ??? ?if(roi_rub_low.at<uchar>(i,j) != roi_bw_high.at<uchar>(i,j))
?? ??? ??? ?{
?? ??? ??? ??? ?rubArea.at<uchar>(i,j) = 255;
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?imshow("復(fù)偏",rubArea);
?? ?waitKey(0);*/
?? ?dilate(rubArea,rubArea,getStructuringElement(MORPH_ELLIPSE,Size(3,3),Point(1,1)));
?? ?erode(rubArea,rubArea,getStructuringElement(MORPH_ELLIPSE,Size(5,5),Point(2,2)));//腐蝕,允許小偏差存在
?? ?/*imshow("復(fù)偏",rubArea);
?? ?waitKey(0);*/
?? ?//將復(fù)偏檢測結(jié)果存放到結(jié)果結(jié)構(gòu)體
?? ?vector<vector<Point>> rub_contours;
?? ?vector<Point> maxContours;
?? ?vector<Vec4i> rub_hierarchy;
?? ?int maxIndex = 0;
?? ?rubConImg = Mat::zeros(rubArea.size(),CV_8UC1);
?? ?findContours(rubArea,rub_contours,rub_hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_NONE);
?? ?for(int i = 0;i<rub_contours.size();i++)
?? ?{
?? ??? ?if(rub_contours[i].size()>rub_contours[maxIndex].size())
?? ??? ??? ?maxIndex = i;?? ??? ?
?? ?}
?? ?if(!rub_contours.empty())
?? ?{
?? ??? ?maxContours = rub_contours[maxIndex];
?? ??? ?double dist = sqrt((double)(maxContours[0].x-roi_centerX)*(maxContours[0].x-roi_centerX)+(maxContours[0].y-roi_centerY)*(maxContours[0].y-roi_centerY));
?? ??? ?if(maxContours.size()>fpArea && dist<(roi_radius+20))
?? ??? ?{
?? ??? ??? ?#pragma omp parallel for
?? ??? ??? ?for(int i = 0;i<maxContours.size();++i)//找到復(fù)偏
?? ??? ??? ?{
?? ??? ??? ??? ?maxContours[i].x = maxContours[i].x + center.x - R -addroi+addX;
?? ??? ??? ??? ?maxContours[i].y = maxContours[i].y + center.y - R -addroi+addY;
?? ??? ??? ?}
?? ??? ??? ?memResult->drub.push_back(maxContours);//檢出復(fù)偏,賦值給結(jié)果結(jié)構(gòu)體
?? ??? ??? ?result[imgIndex][1] = 1;
?? ??? ?}
?? ?}
?? ?//cvtColor(roi,roiRGB,CV_GRAY2BGR);
?? ?//circle(roi,Point(cvRound(roi_centerX),cvRound(roi_centerY)),R,Scalar(155,50,255),1,8,0);
?? ?//----------------------膜內(nèi)黑白點(diǎn)、膜皺檢測---------------------//
?? ?//黑點(diǎn)白點(diǎn)判斷依據(jù):與背景的對比度、大小、與圓心的距離
?? ?//膜皺判斷依據(jù):與背景的對比度、大小、與圓心的距離
?? ?Mat roi_threold_bk,roi_threold_wt,roi_threold_result;
?? ?vector<vector<Point>> spot_contours;
?? ?vector<Vec4i> spot_hierarchy;
?? ?medianBlur(roi,roi,3);
?? ?threshold(roi,roi_threold_wt,avePixel+15,255,THRESH_BINARY);
?? ?threshold(roi,roi_threold_bk,avePixel-15,255,THRESH_BINARY_INV);
?? ?for(int i = 0;i<roi.rows;i++)
?? ?{
?? ??? ?for(int j = 0;j<roi.cols;j++)
?? ??? ?{
?? ??? ??? ?double x2 = (j-roi_centerX)*(j-roi_centerX);
?? ??? ??? ?double y2 = (i-roi_centerY)*(i-roi_centerY);
?? ??? ??? ?double dist = sqrt(x2+y2)-roi_radius;?
?? ??? ??? ?if(dist>-25)
?? ??? ??? ?{
?? ??? ??? ??? ?roi_threold_wt.at<uchar>(i,j) = 0;
?? ??? ??? ??? ?roi_threold_bk.at<uchar>(i,j) = 0;
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?//imshow("kaishihou1",roi_threold_wt);
?? ?//waitKey(0);
?? ?//imshow("kaishihou2",roi_threold_bk);
?? ?//waitKey(0);
?? ?addWeighted(roi_threold_bk,1.0,roi_threold_wt,1.0,0,roi_threold_result);//統(tǒng)計(jì)兩次的結(jié)果
?? ?//adaptiveThreshold(roi,roiblur,255,ADAPTIVE_THRESH_MEAN_C,THRESH_BINARY_INV,11,5);
?? ?
?? ?/*adaptiveThreshold(roi,roiblur,255,ADAPTIVE_THRESH_MEAN_C,THRESH_BINARY_INV,15,10);
?? ?erode(roiblur,roiblur,getStructuringElement(MORPH_RECT,Size(3,3)));
?? ?dilate(roiblur,roiblur,getStructuringElement(MORPH_RECT,Size(3,3)));*/
?? ?
?? ?/*for(int i = 0;i<roiblur.rows;i++)
?? ?{
?? ??? ?for(int j = 0;j<roiblur.cols;j++)
?? ??? ?{
?? ??? ??? ?double dist = sqrt((double)(i-roi_centerX)*(i-roi_centerX)+(j-roi_centerY)*(j-roi_centerY))-roi_radius;
?? ??? ??? ?if(dist > -30)
?? ??? ??? ?{
?? ??? ??? ??? ?roiblur.at<char>(i,j) = 0;
?? ??? ??? ?}
?? ??? ?}
?? ?}*/
?? ?/*imshow("tu",roiblur);
?? ?waitKey(0);*/
?? ?//addWeighted(roiblur,1.0,roi_threold_result1,1.0,0,roi_threold_result);//統(tǒng)計(jì)兩次的結(jié)果
?? ?//imshow("tu",roi_threold_result);
?? ?//waitKey(0);
?? ?Mat roi_contours = Mat::zeros(roi_threold_result.size(),CV_8UC1);//初始化輪廓圖
?? ?Mat old_roi_threold_result;
?? ?roi_threold_result.copyTo(old_roi_threold_result);
?? ?findContours(roi_threold_result,spot_contours,spot_hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_NONE);
?? ?
?? ?contourSort(spot_contours);
?? ?/*for(int i = 0;i<spot_contours[6].size();i++)
?? ?{
?? ??? ?circle(roi_contours,spot_contours[6][i],0,Scalar(255,255,255),-1);
?? ?}*/
?? ?/*imshow("roi",roi_contours);
?? ?waitKey(0);*/
?? ?for(int i = 0;i<spot_contours.size();i++)
?? ?{
?? ??? ?if(spot_contours[i].size()>500)
?? ??? ??? ?continue;
?? ??? ?int contourPixel_local = spot_contours[i].size()/2;
?? ??? ?Point contourPixel = spot_contours[i][contourPixel_local];
?? ??? ?double x2 = (contourPixel.x-roi_centerX)*(contourPixel.x-roi_centerX);
?? ??? ?double y2 = (contourPixel.y-roi_centerY)*(contourPixel.y-roi_centerY);
?? ??? ?double dist = sqrt(x2+y2);
?? ??? ?if(dist < (roi_radius-bwdist))//距離判斷
?? ??? ?{
?? ??? ??? ?int localPixelAve = 0;
?? ??? ??? ?int localPixelCount = 0;
?? ??? ??? ?int localPixelSum = 0;
?? ??? ??? ?int localContrast = 0;
?? ??? ??? ?Rect contourRect;
?? ??? ??? ?contourRect = boundingRect(spot_contours[i]);
?? ??? ??? ?for(int j = contourRect.x;j<contourRect.x+contourRect.width;j++)
?? ??? ??? ?{
?? ??? ??? ??? ?//uchar* data = roi.ptr<uchar>(j);
?? ??? ??? ??? ?for(int k = contourRect.y;k<contourRect.y+contourRect.height;k++)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?double iscontour = pointPolygonTest(spot_contours[i],Point(j,k),false);
?? ??? ??? ??? ??? ?if(iscontour == 1 || iscontour == 0)
?? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ?localPixelCount++;
?? ??? ??? ??? ??? ??? ?localPixelSum = localPixelSum + roi.at<uchar>(k,j);
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ??? ?if(localPixelCount!=0)//排除除0異常
?? ??? ??? ?{
?? ??? ??? ??? ?localPixelAve = (int)(localPixelSum/localPixelCount);
?? ??? ??? ?}
?? ??? ??? ?localContrast = abs(localPixelAve - avePixel);
?? ??? ??? ?if(localContrast > memOffset && localPixelCount <= minMemBwArea &&localPixelCount > memBwArea)//背景對比度+面積判斷
?? ??? ??? ?{
?? ??? ??? ??? ?vector<Point> bwContours = spot_contours[i];
?? ??? ??? ??? ?for(int m = 0;m<spot_contours[i].size();m++)//找到黑點(diǎn)或白點(diǎn)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?bwContours[m].x = bwContours[m].x + center.x - R -addroi+addX;
?? ??? ??? ??? ??? ?bwContours[m].y = bwContours[m].y + center.y - R -addroi+addY;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?memResult->bwspot.push_back(bwContours);//檢出黑白點(diǎn),賦值給結(jié)果結(jié)構(gòu)體
?? ??? ??? ??? ?result[imgIndex][2] = 1;
?? ??? ??? ?}
?? ??? ??? ?if(localContrast > memOffset && localPixelCount > minMemBwArea)//背景對比度+面積判斷
?? ??? ??? ?{
?? ??? ??? ??? ?vector<Point> memContours = spot_contours[i];
?? ??? ??? ??? ?for(int m = 0;m<spot_contours[i].size();m++)//找到膜皺
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?memContours[m].x = memContours[m].x + center.x - R -addroi+addX;
?? ??? ??? ??? ??? ?memContours[m].y = memContours[m].y + center.y - R -addroi+addY;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?memResult->crease.push_back(memContours);//檢出膜皺,賦值給結(jié)果結(jié)構(gòu)體
?? ??? ??? ??? ?result[imgIndex][3] = 1;
?? ??? ??? ?}
?? ??? ?}
?? ?}?? ?
?? ?
?? ?return 0;
}
//缺孔、移位
int localDetect(const Mat srcImg,int result[][10],int hole,int imgIndex,int levcover,int udLeave,Point circlePoint[])
{
?? ?Mat img,gray,bw1,bw2;
?? ?img = srcImg;
?? ?int xP = circlePoint[imgIndex].x;
?? ?int yP = circlePoint[imgIndex].y;
?? ?Point bigCircle = circlePoint[imgIndex];
?? ?if(localEdges[imgIndex].empty() || circleEdges[imgIndex].empty() || bigCircle.x == 0)
?? ?{
?? ??? ?for(int i = 0;i<10;i++)
?? ??? ?{
?? ??? ??? ?result[imgIndex][i] = -10;
?? ??? ?}
?? ??? ?deError[imgIndex] = 8;
?? ??? ?return -1;
?? ?}
?? ?if(img.channels() == 3)
?? ??? ?cvtColor(srcImg,gray,CV_RGB2GRAY);
?? ?else
?? ??? ?gray = img;
?? ?GaussianBlur(gray,gray,Size(5,5),2,2);
?? ?int pixel_level = 0;
?? ?//int pixel_level[256] = {0};//256個(gè)水平
?? ?//double threold_kong = 0.0;
?? ?//double pixelNum = 0.0;
?? ?//double pixelSum = 0.0;
?? ?for(int i = 0;i<gray.rows;i++)
?? ?{
?? ??? ?uchar* data = gray.ptr<uchar>(i);
?? ??? ?for(int j = 0;j<gray.cols;j++)
?? ??? ?{
?? ??? ??? ?int temp = data[j];
?? ??? ??? ?if(temp > 220)
?? ??? ??? ?pixel_level++;//相應(yīng)的像素水平加1
?? ??? ?}
?? ?}
?? ?if(pixel_level<800000)
?? ?{
?? ??? ?for(int i = 0;i<10;i++)
?? ??? ?{
?? ??? ??? ?result[imgIndex][i] = -11;
?? ??? ?}
?? ??? ?deError[imgIndex] = 9;
?? ??? ?return -2;
?? ?}
?? ?//for(int i = 245;i>180;i--)
?? ?//{
?? ?//?? ?if(pixel_level[i]>100)
?? ?//?? ?{
?? ?//?? ??? ?pixelSum = pixelSum + pixel_level[i]*i;
?? ?//?? ??? ?pixelNum = pixelNum + pixel_level[i];
?? ?//?? ?}
?? ?//}
?? ?//threold_kong = pixelSum/pixelNum-20; ?//背景像素值
?? ?threshold(gray,bw1,220,255,CV_THRESH_BINARY);
?? ?//threshold(gray,bw2,100,255,CV_THRESH_BINARY);
?? ?GaussianBlur(bw1,bw1,Size(5,5),2,2);
?? ?//GaussianBlur(bw2,bw2,Size(5,5),2,2);
?? ?Mat bw1con;
?? ?bw1.copyTo(bw1con);
?? ?vector<vector<Point>> bw1ConCount;
?? ?vector<Vec4i> bw1Hierarchy;
?? ?findContours(bw1con,bw1ConCount,bw1Hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE);
?? ?if(bw1ConCount.size()>500)
?? ?{
?? ??? ?for(int i = 0;i<10;i++)
?? ??? ?{
?? ??? ??? ?result[imgIndex][i] = -12;//沒有檢測到圓,無樣本,返回-1
?? ??? ?}
?? ??? ?deError[imgIndex] = 10;
?? ??? ?return -1;
?? ?}
?? ?vector<Vec3f> hough_circles;
?? ?//vector<Vec3f> hough_circles1;
?? ?/*namedWindow("二值圖1",0);
?? ?imshow("二值圖1",bw1);
?? ?waitKey(0);*/
?? ?/*namedWindow("二值圖",0);
?? ?imshow("二值圖",bw2);
?? ?waitKey(0);*/
?? ?//霍夫圓變換粗定位圓,累加器為原圖像2/3,最小圓心距離5,canny高閾值,圓檢測閾值60,越小越能檢測到不規(guī)則的圓
?? ?HoughCircles(bw1,hough_circles,CV_HOUGH_GRADIENT,1.5,80,200,90,0,0);
?? ?//HoughCircles(bw2,hough_circles1,CV_HOUGH_GRADIENT,1.5,5,200,110,0,0);
?? ?int circleNum = 0;
?? ?Point smaCircle(0,0);
?? ?if(!hough_circles.empty())
?? ?{
?? ??? ?smaCircle.x = hough_circles[0][0];
?? ??? ?smaCircle.y = hough_circles[0][1];
?? ?}
?? ?else
?? ?{
?? ??? ?for(int i = 0;i<10;i++)
?? ??? ?{
?? ??? ??? ?result[imgIndex][i] = -13;
?? ??? ?}
?? ??? ?deError[imgIndex] = 11;
?? ??? ?return -3;
?? ?}
?? ?/*if(!hough_circles1.empty())
?? ?{
?? ??? ?for(int i = 0;i<hough_circles1.size();i++)
?? ??? ?{
?? ??? ??? ?if(hough_circles1[i][2]>100 && hough_circles1[i][2]<130)
?? ??? ??? ?{
?? ??? ??? ??? ?bigCircle.x = hough_circles1[i][0];
?? ??? ??? ??? ?bigCircle.y = hough_circles1[i][1];
?? ??? ??? ?}
?? ??? ?}
?? ?}*/
?? ?int dif = 0;
?? ?if(bigCircle.y!=0)
?? ??? ?dif = abs(bigCircle.y - hough_circles[0][1]);
?? ?for(size_t i = 0;i<hough_circles.size();i++)
?? ?{
?? ??? ?Point center(cvRound(hough_circles[i][0]),cvRound(hough_circles[i][1]));
?? ??? ?int radius = cvRound(hough_circles[i][2]);
?? ??? ?if(radius<120 && radius>65)
?? ??? ?{
?? ??? ??? ?//circle(bw1,center,radius,Scalar(155,50,255),1,8,0);
?? ??? ??? ?circleNum++;
?? ??? ??? ?if(bigCircle.y!=0)
?? ??? ??? ?{
?? ??? ??? ??? ?int temp = abs(bigCircle.y - center.y);
?? ??? ??? ??? ?if(dif!=0 && temp<dif)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?dif = temp;
?? ??? ??? ??? ??? ?smaCircle = center;
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?/*double dist = 0;
?? ?if(bigCircle.y!=0 && smaCircle.y!=0)
?? ?{
?? ??? ?double x2 = (bigCircle.x - smaCircle.x)*(bigCircle.x - smaCircle.x);
?? ??? ?double y2 = (bigCircle.y - smaCircle.y)*(bigCircle.y - smaCircle.y);
?? ??? ?dist = sqrt(x2+y2);
?? ?}*/
?? ?//circle(bw1,bigCircle,3,Scalar(155,50,255),-1);
?? ?//circle(bw1,smaCircle,3,Scalar(155,50,255),-1);
?? ?/*imshow("huofu",bw1);
?? ?waitKey(0);*/
?? ?//dist = dist - 425;
?? ?Point up(0,0);
?? ?Point down(0,0);
?? ?Point leftP(0,0);
?? ?Point rightP(0,0);
?? ?double gradientUp = 0;
?? ?double gradientDown = 0;
?? ?double gradientLOrR = 0;
#pragma omp parallel for
?? ?for(int i = 0;i<localEdges[imgIndex].size();i++)
?? ?{
?? ??? ?if(localEdges[imgIndex][i].x == xP)
?? ??? ?{
?? ??? ??? ?if(localEdges[imgIndex][i].y < circlePoint[imgIndex].y)
?? ??? ??? ??? ?up = localEdges[imgIndex][i];
?? ??? ??? ?else
?? ??? ??? ??? ?down = localEdges[imgIndex][i];
?? ??? ?}
?? ??? ?if(localEdges[imgIndex][i].y == yP)
?? ??? ?{
?? ??? ??? ?if(localEdges[imgIndex][i].x < circlePoint[imgIndex].x)
?? ??? ??? ??? ?leftP = localEdges[imgIndex][i];
?? ??? ??? ?else
?? ??? ??? ??? ?rightP = localEdges[imgIndex][i];
?? ??? ?}
?? ?}
?? ?if(up.x != 0 && down.x != 0 && rightP.x!=0 && leftP.x!=0)
?? ?{
?? ??? ?for(int i = udLeave;i<100;i++)
?? ??? ?{
?? ??? ??? ?Point pt1(up.x,up.y-i);
?? ??? ??? ?Point pt2(down.x,down.y+i);
?? ??? ??? ?Point pt3(up.x,up.y-i-1);
?? ??? ??? ?Point pt4(down.x,down.y+i+1);
?? ??? ??? ?if( pt3.y<0 || pt4.y>srcImg.rows-1)
?? ??? ??? ??? ?continue;
?? ??? ??? ?double pixel1 = srcImg.at<uchar>(pt1);
?? ??? ??? ?double pixel2 = srcImg.at<uchar>(pt3);
?? ??? ??? ?double pixel3 = srcImg.at<uchar>(pt2);
?? ??? ??? ?double pixel4 = srcImg.at<uchar>(pt4);
?? ??? ??? ?double temp1 = abs(pixel1-pixel2);
?? ??? ??? ?double temp2 = abs(pixel3-pixel4);
?? ??? ??? ?gradientUp = gradientUp + temp1;
?? ??? ??? ?gradientDown = gradientDown + temp2;
?? ??? ?}
?? ??? ?if(imgIndex==0 || imgIndex==2)
?? ??? ?{
?? ??? ??? ?for(int i = levcover;i<100;i++)
?? ??? ??? ?{
?? ??? ??? ??? ?Point pt1(rightP.x+i,rightP.y);?? ??? ??? ?
?? ??? ??? ??? ?Point pt3(rightP.x+i+1,rightP.y);
?? ??? ??? ??? ?if( pt3.x>srcImg.cols-1)
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?double pixel1 = srcImg.at<uchar>(pt1);
?? ??? ??? ??? ?double pixel2 = srcImg.at<uchar>(pt3);
?? ??? ??? ??? ?double temp1 = abs(pixel1-pixel2);
?? ??? ??? ??? ?gradientLOrR = gradientLOrR + temp1;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?if(imgIndex==1 || imgIndex==3)
?? ??? ?{
?? ??? ??? ?for(int i = levcover;i<100;i++)
?? ??? ??? ?{
?? ??? ??? ??? ?Point pt1(leftP.x-i,rightP.y);?? ??? ??? ?
?? ??? ??? ??? ?Point pt3(leftP.x-i-1,rightP.y);
?? ??? ??? ??? ?if( pt3.x<0)
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?double pixel1 = srcImg.at<uchar>(pt1);
?? ??? ??? ??? ?double pixel2 = srcImg.at<uchar>(pt3);
?? ??? ??? ??? ?double temp1 = abs(pixel1-pixel2);
?? ??? ??? ??? ?gradientLOrR = gradientLOrR + temp1;
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?if(circleNum<hole)
?? ?{
?? ??? ?result[imgIndex][4] = 1;//缺孔
?? ?}
?? ?if(gradientUp>100 && result[imgIndex][5]==0)
?? ??? ?result[imgIndex][5] = 3;//下移位
?? ?if(gradientLOrR>100 && result[imgIndex][5]==0)
?? ?{
?? ??? ?result[imgIndex][5] = 2;//左右移位
?? ?}
?? ?if(gradientDown>100 && result[imgIndex][5]==0)
?? ??? ?result[imgIndex][5] = 1;//上移位
}
int lackMaterial(int result[][10],Mat srcImage,int imgIndex)
{?? ?
?? ?Mat img,bw,combw;
?? ?int memThreold = 50;?? ?//提取中心膜時(shí)二值化閾值
?? ?img = srcImage;
?? ?Mat tempL,tempR;
?? ?mask_left.copyTo(tempL);
?? ?mask_right.copyTo(tempR);
?? ?threshold(tempL,tempL,memThreold,255,CV_THRESH_BINARY);//模版轉(zhuǎn)為二值圖
?? ?threshold(tempR,tempR,memThreold,255,CV_THRESH_BINARY);
?? ?
?? ?int resultImage_cols = img.cols - mask_left.cols + 1;
?? ?int resultImage_rows = img.rows - mask_left.rows + 1;
?? ?if(resultImage_cols<=0 || resultImage_rows<=0)
?? ?{
?? ??? ?for(int i = 0;i < 4;i++)
?? ??? ?{
?? ??? ??? ?for(int j = 0;j<10;j++)
?? ??? ??? ?{
?? ??? ??? ??? ?result[i][j] = -17;//結(jié)果圖為空
?? ??? ??? ?}
?? ??? ?}
?? ??? ?deError[imgIndex] = 15;
?? ??? ?return -1;
?? ?}
?? ?Mat resultImage;
?? ?resultImage.create(resultImage_cols,resultImage_rows,CV_32FC1);
?? ?threshold(img,bw,memThreold,255,CV_THRESH_BINARY);
?? ?
?? ?GaussianBlur(bw,bw,Size(5,5),2,2);?
?? ?/*imshow("huofu",bw);
?? ?waitKey(0);*/
?? ?vector<Vec3f> hough_circles;
?? ?//霍夫圓變換粗定位圓,累加器為原圖像2/3,最小圓心距離5,canny高閾值,圓檢測閾值60,越小越能檢測到不規(guī)則的圓
?? ?HoughCircles(bw,hough_circles,CV_HOUGH_GRADIENT,1.5,10,200,100,50,0);
?? ?if(hough_circles.empty())
?? ??? ?return -1;
?? ?int maxCircle = -1;//找出合適大小的圓
?? ?for(int i = 0;i<hough_circles.size();i++)
?? ?{
?? ??? ?if(hough_circles[i][2] < 140 && hough_circles[i][2]>100)
?? ??? ?{
?? ??? ??? ?maxCircle = i;
?? ??? ?}
?? ?}
?? ?if(maxCircle == -1)
?? ??? ?return -1;
?? ?int flag = hough_circles[maxCircle][0] - srcImage.cols/2;
?? ?threshold(srcImage,combw,memThreold,255,CV_THRESH_BINARY);
?? ?/*imshow("left",tempL);
?? ?waitKey(0);
?? ?imshow("right",tempR);
?? ?waitKey(0);
?? ?imshow("2",combw);
?? ?waitKey(0);*/
?? ?if(flag > 0)
?? ?{
?? ??? ?matchTemplate(combw,tempR,resultImage,TM_SQDIFF);?? ?
?? ?}
?? ?else
?? ?{
?? ??? ?matchTemplate(combw,tempL,resultImage,TM_SQDIFF);
?? ?}
?? ?//normalize(resultImage,resultImage,0,1,NORM_MINMAX,-1,Mat());
?? ?double minValue;double maxValue;
?? ?Point minlocation;Point maxLocation;Point matchLocation;
?? ?minMaxLoc(resultImage,&minValue,&maxValue,&minlocation,&maxLocation,Mat());
?? ?int queliao = (int)(minValue/1000000);
?? ?if(queliao>950)
?? ??? ?result[imgIndex][7] = 1;//檢測到缺料
?? ?return 0;
}
//感興趣區(qū)域提取
int getRoiImg(const Mat srcImg,int sampleNum,vector<Mat>& roiImgs,int result[][10])
{
?? ?Mat grayImg,bwImg,blurImg;
?? ?int roi_threold = 23;?? ??? ?//提取感興趣區(qū)域時(shí)的閾值
?? ?if(srcImg.channels() == 3)
?? ??? ?cvtColor(srcImg,grayImg,CV_RGB2GRAY);
?? ?else if(srcImg.channels() == 1)
?? ?{
?? ??? ?grayImg = srcImg;
?? ?}
?? ?medianBlur(grayImg,blurImg,3);
?? ?threshold(blurImg,bwImg,roi_threold,255,THRESH_BINARY_INV);
?? ?/*namedWindow("二值圖",CV_WINDOW_NORMAL);
?? ?imshow("二值圖",bwImg);
?? ?waitKey(0);*/
?? ?vector<vector<Point>> contours;
?? ?vector<Vec4i> hierarchy;
?? ?findContours(bwImg,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_NONE,Point(0,0));
?? ?if(contours.size()<sampleNum)
?? ?{
?? ??? ?for(int i = 0;i < 4;i++)
?? ??? ?{
?? ??? ??? ?for(int j = 0;j<10;j++)
?? ??? ??? ?{
?? ??? ??? ??? ?result[i][j] = -2;//檢測到的輪廓小于樣本輪廓
?? ??? ??? ?}
?? ??? ?}
?? ??? ?return -1;
?? ?}
?? ?contourSort(contours);
?? ?if(contours.size()<sampleNum)
?? ??? ?sampleNum = contours.size();
?? ?vector<vector<Point>> getcontours;
?? ?vector<Point> CT1;
?? ?vector<Point> CT2;
?? ?vector<Point> CT3;
?? ?vector<Point> CT4;
?? ?for(int i = 0;i<sampleNum && i<contours.size()-1;i++)
?? ?{
?? ??? ?int x = contours[i][0].x;
?? ??? ?int y = contours[i][0].y;
?? ??? ?if(x<1226&&y<1028&&contours[i].size()>1200&&contours[i].size()<1720)
?? ??? ?{
?? ??? ??? ?CT1 = contours[i];
?? ??? ?}
?? ??? ?if(x>1226&&y<1028&&contours[i].size()>1200&&contours[i].size()<1720)
?? ??? ?{
?? ??? ??? ?CT2 = contours[i];
?? ??? ?}
?? ??? ?if(x<1226&&y>1028&&contours[i].size()>1200&&contours[i].size()<1720)
?? ??? ?{
?? ??? ??? ?CT3 = contours[i];
?? ??? ?}
?? ??? ?if(x>1226&&y>1028&&contours[i].size()>1200&&contours[i].size()<1720)
?? ??? ?{
?? ??? ??? ?CT4 = contours[i];
?? ??? ?}
?? ?}
?? ?contours[0] = CT1;
?? ?contours[1] = CT2;
?? ?contours[2] = CT3;
?? ?contours[3] = CT4;
?? ?for(int i = 0;i<sampleNum;i++)
?? ?{
?? ??? ?getcontours.push_back(contours[i]);
?? ??? ?if(i==0)
?? ??? ?{?? ??? ??? ?
?? ??? ??? ?localEdges.push_back(contours[i]);
?? ??? ?}
?? ??? ?if(i==1)
?? ??? ?{
?? ??? ??? ?vector<Point> temp;
?? ??? ??? ?for(int j = 0;j<contours[i].size();++j)
?? ??? ??? ?{
?? ??? ??? ??? ?Point temp1(contours[i][j].x-1226,contours[i][j].y);
?? ??? ??? ??? ?temp.push_back(temp1);
?? ??? ??? ?}
?? ??? ??? ?localEdges.push_back(temp);
?? ??? ?}
?? ??? ?if(i==2)
?? ??? ?{
?? ??? ??? ?vector<Point> temp;
?? ??? ??? ?for(int j = 0;j<contours[i].size();++j)
?? ??? ??? ?{
?? ??? ??? ??? ?Point temp1(contours[i][j].x,contours[i][j].y-1028);
?? ??? ??? ??? ?temp.push_back(temp1);
?? ??? ??? ?}
?? ??? ??? ?localEdges.push_back(temp);
?? ??? ?}
?? ??? ?if(i==3)
?? ??? ?{
?? ??? ??? ?vector<Point> temp;
?? ?
?? ??? ??? ?for(int j = 0;j<contours[i].size();++j)
?? ??? ??? ?{
?? ??? ??? ??? ?Point temp1(contours[i][j].x-1226,contours[i][j].y-1028);
?? ??? ??? ??? ?temp.push_back(temp1);
?? ??? ??? ?}
?? ??? ??? ?localEdges.push_back(temp);
?? ??? ?}
?? ?}
?? ?
?? ?//imshow("輪廓圖",ctrImage);
?? ?for(int i = 0;i<getcontours.size();i++)
?? ?{
?? ??? ?if(getcontours[i].empty())
?? ??? ?{
?? ??? ??? ?Mat Idst = Mat::zeros(515,680,CV_8UC1);
?? ??? ??? ?roiImgs.push_back(Idst);
?? ??? ??? ?continue;
?? ??? ?}
?? ??? ?RotatedRect rRect;
?? ??? ?rRect=minAreaRect(getcontours[i]);
?? ??? ?int dstw,dsth;
?? ??? ?Point2f vertices[4];
?? ? ? ?Point2f verdst[4];
?? ??? ?int minBorder = min(rRect.size.height,rRect.size.width);
?? ??? ?int addRect = 100;
?? ??? ?rRect.size.width = rRect.size.width + addRect;
?? ??? ?rRect.size.height = rRect.size.height + addRect;
?? ? ? ?if(rRect.size.width>rRect.size.height)
?? ? ? ?{
? ? ? ? ? rRect.points(vertices);//取得四個(gè)頂點(diǎn)
?? ??? ? ?dstw = rRect.size.width;
? ? ? ? ? dsth = rRect.size.height;
? ? ? ? ? verdst[0] = Point2f(0,dsth);
? ? ? ? ? verdst[1] = Point2f(0,0);
? ? ? ? ? verdst[2] = Point2f(dstw,0);
? ? ? ? ? verdst[3] = Point2f(dstw,dsth);?
? ? ? ? }
? ? ? ? else?
? ? ? ?{
? ? ? ? ?rRect.points(vertices);
? ? ? ? ?dstw = rRect.size.height;
? ? ? ? ?dsth = rRect.size.width;
? ? ? ? ?verdst[0] = Point2f(dstw,dsth);
? ? ? ? ?verdst[1] = Point2f(0,dsth);
? ? ? ? ?verdst[2] = Point2f(0,0);
? ? ? ? ?verdst[3] = Point2f(dstw,0);
? ? ? ?}
? ? ? ?Mat Idst = Mat(dsth,dstw,CV_8UC1);
?? ? ? //Mat dstImg;
? ? ? ?Mat warpMatrix = getPerspectiveTransform(vertices, verdst);
?? ? ? warpPerspective(srcImg, Idst, warpMatrix, Idst.size(), INTER_LINEAR, BORDER_CONSTANT);?
?? ? ? //resize(Idst,dstImg,Size(640,380));
?? ? ? roiImgs.push_back(Idst);
?? ?}
?? ?/*Mat a = roiImgs[0];
?? ?Mat b = roiImgs[3];
?? ?int rowN = (a.rows+b.rows)/2;
?? ?int colN = (a.cols+b.cols)/2;
?? ?resize(a,a,Size(colN,rowN));
?? ?resize(b,b,Size(colN,rowN));
?? ?imshow("1",a);
?? ?waitKey(0);
?? ?imshow("4",b);
?? ?waitKey(0);
?? ?imwrite("mask_left.bmp",a);
?? ?imwrite("mask_right.bmp",b);*/
?? ?return 0;
}
//------------外輪廓臟點(diǎn)、壓印檢測------------//
int badSpot(Mat srcImg,vector<vector<Point>>& ctspot,const Point circlepoint[],int leavCenter[],const RubDetectParams rubParams,int imgIndex,vector<vector<Point2f>>& roRect,int result[][10])
{
?? ?int addX = 0;
?? ?int addY = 0;
?? ?if(imgIndex == 1)
?? ?{
?? ??? ?addX = dst_height/2;
?? ?}
?? ?if(imgIndex == 2)
?? ?{
?? ??? ?addY = dst_width/2;
?? ?}
?? ?if(imgIndex == 3)
?? ?{
?? ??? ?addX = dst_height/2;
?? ??? ?addY = dst_width/2;
?? ?}
?? ?Mat Img;
?? ?srcImg.copyTo(Img);
?? ?if(localEdges[imgIndex].empty() || circleEdges[imgIndex].empty())
?? ?{
?? ??? ?for(int i = 0;i < 4;i++)
?? ??? ?{
?? ??? ??? ?for(int j = 0;j<10;j++)
?? ??? ??? ?{
?? ??? ??? ??? ?result[i][j] = -14;//檢測到的輪廓小于樣本輪廓
?? ??? ??? ?}
?? ??? ?}
?? ??? ?deError[imgIndex] = 12;
?? ??? ?return -1;
?? ?}
?? ?int minY = localEdges[imgIndex][0].y;
?? ?int maxY = localEdges[imgIndex][0].y;
#pragma omp parallel for
?? ?for(int i = 0;i<localEdges[imgIndex].size();i+=14)
?? ?{
?? ??? ?if(localEdges[imgIndex][i].y<minY)
?? ??? ??? ?minY = localEdges[imgIndex][i].y;
?? ??? ?if(localEdges[imgIndex][i].y>maxY)
?? ??? ??? ?maxY = localEdges[imgIndex][i].y;
?? ??? ?for(int j = -12;j<13;j++)
?? ??? ??? ?for(int k = -12;k<13;k++)
?? ??? ??? ?{
?? ??? ??? ??? ?int x = localEdges[imgIndex][i].y+j;
?? ??? ??? ??? ?int y = localEdges[imgIndex][i].x+k;
?? ??? ??? ??? ?if(x<0)
?? ??? ??? ??? ??? ?x = 0;
?? ??? ??? ??? ?if(y<0)
?? ??? ??? ??? ??? ?y = 0;
?? ??? ??? ? ? ?if(x>=Img.rows)
?? ??? ??? ??? ??? ?x = Img.rows-1;
?? ??? ??? ??? ?if(y>=Img.cols)
?? ??? ??? ??? ??? ?y = Img.cols-1;
?? ??? ??? ??? ?Img.at<char>(x,y) = 32;
?? ??? ??? ?}
?? ?}
#pragma omp parallel for
?? ?for(int i = 0;i<circleEdges[imgIndex].size();i+=8)
?? ?{
?? ??? ?for(int j = -6;j<7;j++)
?? ??? ??? ?for(int k = -6;k<7;k++)
?? ??? ??? ?{
?? ??? ??? ??? ?int x = circleEdges[imgIndex][i].y+j;
?? ??? ??? ??? ?int y = circleEdges[imgIndex][i].x+k;
?? ??? ??? ??? ?if(x<0)
?? ??? ??? ??? ??? ?x = 0;
?? ??? ??? ??? ?if(y<0)
?? ??? ??? ??? ??? ?y = 0;
?? ??? ??? ? ? ?if(x>=Img.rows)
?? ??? ??? ??? ??? ?x = Img.rows-1;
?? ??? ??? ??? ?if(y>=Img.cols)
?? ??? ??? ??? ??? ?y = Img.cols-1;
?? ??? ??? ??? ?Img.at<char>(x,y) = 32;
?? ??? ??? ?}
?? ?}
?? ?Mat gray,bw;?? ??? ??? ?
?? ?int memffset = rubParams.memOffset;?? ??? ?
?? ?int memRubDist = rubParams.memRubDist;?? ??? ??? ?
?? ?int rubPixel = rubParams.rubPixelDif;?? ??? ?
?? ?int rubPixelArea = rubParams.rubPixelArea;?? ??? ?
?? ?int reaHoleNum = rubParams.holeNum + 2;
?? ?int rubThreold = rubParams.rubThreold;
?? ?//GaussianBlur(Img,gray,Size(3,3),2,2);
?? ?threshold(Img,bw,rubThreold,255,CV_THRESH_BINARY);
?? ?/*namedWindow("erzhitu",0);
?? ?imshow("erzhitu",bw);
?? ?waitKey(0);*/
?? ?
?? ?vector<vector<Point>> bwContours;
?? ?vector<Vec4i> bwHierarchy;
?? ?Mat bwContoursImg = Mat::zeros(bw.size(),CV_8UC1);
?? ?Mat oldBw;
?? ?bw.copyTo(oldBw);
?? ?findContours(oldBw,bwContours,bwHierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_NONE);
?? ?if(bwContours.size()>300)
?? ?{
?? ??? ?for(int i = 0;i < 4;++i)
?? ??? ?{
?? ??? ??? ?for(int j = 0;j<10;++j)
?? ??? ??? ?{
?? ??? ??? ??? ?result[i][j] = -15;//檢測到的輪廓太多
?? ??? ??? ?}
?? ??? ?}
?? ??? ?deError[imgIndex] = 13;
?? ??? ?return -1;
?? ?}
?? ?//findContours(bw,bwContours,bwHierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE);
?? ?/*for(int index = 0;index<bwContours.size();index++)
?? ?{
?? ??? ?drawContours(bwContoursImg,bwContours,index,Scalar(255,255,255),1,8,bwHierarchy);
?? ?}*/
?? ?contourSort(bwContours);
?? ?for(int i = reaHoleNum;i<bwContours.size();i++)
?? ?{
?? ??? ?int contSize = bwContours[i].size();
?? ??? ?if(contSize>500)
?? ??? ??? ?continue;
?? ??? ?double flag1 = pointPolygonTest(bwContours[1],bwContours[i][0],false);
?? ??? ?double flag2 = pointPolygonTest(bwContours[2],bwContours[i][0],false);
?? ??? ?int localPixelAve = 0;
?? ??? ?int localPixelCount = 0;
?? ??? ?int localPixelSum = 0;
?? ??? ?int localContrast = 0;
?? ??? ?Rect contourRect;
?? ??? ?contourRect = boundingRect(bwContours[i]);
?? ??? ?for(int j = contourRect.x;j<contourRect.x+contourRect.width;j++)
?? ??? ?{
?? ??? ??? ?//uchar* data = roi.ptr<uchar>(j);
?? ??? ??? ?for(int k = contourRect.y;k<contourRect.y+contourRect.height;k++)
?? ??? ??? ?{
?? ??? ??? ??? ?double iscontour = pointPolygonTest(bwContours[i],Point(j,k),false);
?? ??? ??? ??? ?if(iscontour == 1 || iscontour == 0)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?if(k<0 || j<0 || k>srcImg.rows || j>srcImg.cols)
?? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ?for(int i = 0;i < 4;i++)
?? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ?for(int j = 0;j<10;j++)
?? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ??? ?result[i][j] = -16;//檢測到的輪廓小于樣本輪廓
?? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ?deError[imgIndex] = 14;
?? ??? ??? ??? ??? ??? ?return -1;
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ?localPixelCount++;
?? ??? ??? ??? ??? ?localPixelSum = localPixelSum + srcImg.at<uchar>(k,j);
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
?? ??? ?if(localPixelCount!=0)//排除除0異常
?? ??? ?{
?? ??? ??? ?localPixelAve = (int)(localPixelSum/localPixelCount);
?? ??? ?}
?? ??? ?localContrast = localPixelAve - 32;
?? ??? ?if(bwContours[i].size() > rubPixelArea && flag1 == 1 && flag2 == -1)
?? ??? ?{
?? ??? ??? ?int difY1 = abs(bwContours[i][0].y - ?minY);
?? ??? ??? ?int difY2 = abs(bwContours[i][0].y - maxY);
?? ??? ??? ?if(localContrast > rubPixel ?&& difY1>25 && difY2>25)
?? ??? ??? ?{
?? ??? ??? ??? ?vector<Point2f> trot;
?? ??? ??? ??? ?Point2f DT[4] = {0};
?? ??? ??? ??? ?RotatedRect roR = minAreaRect(bwContours[i]);
?? ??? ??? ??? ?roR.points(DT);
?? ??? ??? ??? ?for(int k = 0;k<4;k++)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?DT[k].x = DT[k].x + addX;
?? ??? ??? ??? ??? ?DT[k].y = DT[k].y + addY;
?? ??? ??? ??? ??? ?trot.push_back(DT[k]);
?? ??? ??? ??? ?}
?? ??? ??? ??? ?roRect.push_back(trot);
?? ??? ??? ??? ?result[imgIndex][6] = 1;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?if(bwContours[i].size() < rubPixelArea)
?? ??? ??? ?break;
?? ?}
?? ?return 0;
?? ?//imshow("lunkuo",bwContoursImg);
?? ?//waitKey(0);
?? ?/*contourSort(bwContours);
?? ?drawContours(bwContoursImg,bwContours,1,Scalar(255,255,255),1,8);
?? ?double ctArea = contourArea(bwContours[1]);
?? ?int blackpoint = 0;
?? ?for(int i = 0;i<gray.rows;i++)
?? ?{
?? ??? ?for(int j = 0;j<gray.cols;j++)
?? ??? ?{
?? ??? ??? ?Point temp(i,j);
?? ??? ??? ?if(gray.at<uchar>(i,j)<15 && pointPolygonTest(bwContours[1],temp,false))
?? ??? ??? ?{
?? ??? ??? ??? ?blackpoint++;
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?int a = 0;*/
?? ?//centerOffset(bwContours[1],leavCenter,circlepoint,memRubDist,memffset);
?? ?//if(bwContours.size()>reaHoleNum)?? ?//如果輪廓大于reaHoleNum個(gè)開始判斷
?? ?//{
?? ?//?? ?for(int i = reaHoleNum;i<bwContours.size();i++)//
?? ?//?? ?{
?? ?//?? ??? ?Rect contourRect;
?? ?//?? ??? ?contourRect = boundingRect(bwContours[i]);
?? ?//?? ??? ?int c = bwContours[i].size()/2;
?? ?//?? ??? ?Point contPixel = bwContours[i][c];
?? ?//?? ??? ?int pixelNum = 0;
?? ?//?? ??? ?int pixelSum = 0;
?? ?//?? ??? ?int avePixel = 0;
?? ?//?? ??? ?if(pointPolygonTest(bwContours[1],contPixel,false) != 1)
?? ?//?? ??? ?{
?? ?//?? ??? ??? ?continue;
?? ?//?? ??? ?}
?? ?//?? ??? ?for(int j = contourRect.x;j<=(contourRect.x+contourRect.width);j++)
?? ?//?? ??? ?{
?? ?//?? ??? ??? ?for(int k = contourRect.y;k<=(contourRect.y+contourRect.height);k++)
?? ?//?? ??? ??? ?{
?? ?//?? ??? ??? ??? ?if(pointPolygonTest(bwContours[i],Point(j,k),false) == 1)
?? ?//?? ??? ??? ??? ?{
?? ?//?? ??? ??? ??? ??? ?pixelNum++;
?? ?//?? ??? ??? ??? ??? ?pixelSum = pixelSum + gray.at<uchar>(k,j);
?? ?//?? ??? ??? ??? ?}
?? ?//?? ??? ??? ?}
?? ?//?? ??? ?}
?? ?//?? ??? ?if(pixelNum!=0)
?? ?//?? ??? ?{
?? ?//?? ??? ??? ?avePixel = (int)(pixelSum/pixelNum);
?? ?//?? ??? ?}
?? ?//?? ??? ?if(avePixel>rubPixel && pixelNum>rubPixelArea)//根據(jù)面積和像素值判斷
?? ?//?? ??? ?{
?? ?//?? ??? ??? ?bool flag = false;
?? ?//?? ??? ??? ?if(avePixel>80)
?? ?//?? ??? ??? ?{
?? ?//?? ??? ??? ??? ?ctspot.push_back(bwContours[i]);
?? ?//?? ??? ??? ??? ?flag = true;
?? ?//?? ??? ??? ?}
?? ?//?? ??? ??? ?if(pixelNum>rubPixelArea+5)
?? ?//?? ??? ??? ?{
?? ?//?? ??? ??? ??? ?if(!flag)
?? ?//?? ??? ??? ??? ??? ?ctspot.push_back(bwContours[i]);
?? ?//?? ??? ??? ?}
?? ?//?? ??? ?}
?? ?//?? ??? ?if(i<bwContours.size()-1)
?? ?//?? ??? ?{
?? ?//?? ??? ??? ?if(bwContours[i-1].size()< 20)
?? ?//?? ??? ??? ??? ?break;
?? ?//?? ??? ?}
?? ?//?? ?}
?? ?//}
?? ?//imshow("外輪廓圖",bwContoursImg);
?? ?//imshow("原始圖",img);
?? ?//imshow("二值圖",oldBw);
}
//-------------偏心檢測-----------//
int centerOffset(const Point circlepoint,const int dist,const int maxleav,int memUdOffset,int result[][10],int imgIndex)
{
?? ?int updist = 0;
?? ?int downdist = 0;
?? ?int leftdist = 0;
?? ?int rightdist = 0;
?? ?int updowndist = 0;
?? ?int rldif = 0;
?? ?Point upW(0,0);
?? ?Point upN(0,0);
?? ?Point downW(0,0);
?? ?Point downN(0,0);
?? ?Point rightW(0,0);
?? ?Point rightN(0,0);
?? ?Point leftW(0,0);
?? ?Point leftN(0,0);
?? ?for(int i = 0;i<circleEdges[imgIndex].size();i++)
?? ?{
?? ??? ?if(circleEdges[imgIndex][i].y == circlepoint.y)
?? ??? ?{
?? ??? ??? ?if(circleEdges[imgIndex][i].x<circlepoint.x)
?? ??? ??? ?{
?? ??? ??? ??? ?leftN = circleEdges[imgIndex][i];
?? ??? ??? ?}
?? ??? ??? ?else
?? ??? ??? ??? ?rightN = circleEdges[imgIndex][i];
?? ??? ??? ?continue;
?? ??? ?}
?? ??? ?if(circleEdges[imgIndex][i].x == circlepoint.x)
?? ??? ?{
?? ??? ??? ?if(circleEdges[imgIndex][i].y > circlepoint.y)
?? ??? ??? ?{
?? ??? ??? ??? ?downN = circleEdges[imgIndex][i];
?? ??? ??? ?}
?? ??? ??? ?if(circleEdges[imgIndex][i].y < circlepoint.y)
?? ??? ??? ?{
?? ??? ??? ??? ?upN = circleEdges[imgIndex][i];
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?for(int i = 0;i<localEdges[imgIndex].size();++i)
?? ?{
?? ??? ?if(localEdges[imgIndex][i].x == circlepoint.x)
?? ??? ?{
?? ??? ??? ?if(localEdges[imgIndex][i].y<circlepoint.y)
?? ??? ??? ?{
?? ??? ??? ??? ?upW = localEdges[imgIndex][i];
?? ??? ??? ?}
?? ??? ??? ?else
?? ??? ??? ??? ?downW = localEdges[imgIndex][i];
?? ??? ??? ?continue;
?? ??? ?}
?? ??? ?if(localEdges[imgIndex][i].y == circlepoint.y)
?? ??? ?{
?? ??? ??? ?if(localEdges[imgIndex][i].x > circlepoint.x)
?? ??? ??? ?{
?? ??? ??? ??? ?rightW = localEdges[imgIndex][i];
?? ??? ??? ?}
?? ??? ??? ?if(localEdges[imgIndex][i].x < circlepoint.x)
?? ??? ??? ?{
?? ??? ??? ??? ?leftW = localEdges[imgIndex][i];
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?
?? ?if(upW.x!=0 && downW.x!=0&&upN.x!=0 && downN.x!=0 && rightN.x!=0 && rightW.x!=0 && leftN.x!=0 && leftW.x!=0)
?? ?{
?? ??? ?updist = abs(upN.y - upW.y);
?? ??? ?downdist = abs(downW.y - downN.y);
?? ??? ?rightdist = abs(rightW.x - rightN.x);
?? ??? ?leftdist = abs(leftN.x - leftW.x);
?? ??? ?updowndist = abs(updist-downdist);?? ?
?? ??? ?updowndist = abs(updowndist-158);
?? ??? ?if(imgIndex == 0 || imgIndex == 2)
?? ??? ??? ?rldif = abs(rightdist - 91);
?? ??? ?if(imgIndex == 1 || imgIndex == 3)
?? ??? ??? ?rldif = abs(leftdist - 91);
?? ?}
?? ?if(updowndist>memUdOffset)
?? ?{
?? ??? ?result[imgIndex][8] = 1;
?? ?}
?? ?if(rldif>maxleav)
?? ?{
?? ??? ?result[imgIndex][8] = 2;
?? ?}
?? ?return 0;
}
//最小二乘法擬合圓
bool circleLeastFit(const vector<Point> &points, double ¢er_x, double ¢er_y, double &radius)
{
? ? ?center_x = 0.0f;
? ? ?center_y = 0.0f;
? ? ?radius = 0.0f;
? ? ?if (points.size() < 3)
? ? ?{
? ? ? ? ?return false;
? ? ?}
? ? ?double sum_x = 0.0f, sum_y = 0.0f;
? ? ?double sum_x2 = 0.0f, sum_y2 = 0.0f;
? ? ?double sum_x3 = 0.0f, sum_y3 = 0.0f;
? ? ?double sum_xy = 0.0f, sum_x1y2 = 0.0f, sum_x2y1 = 0.0f;
? ? ?int N = points.size();
? ? ?for (int i = 0; i < N; i++)
? ? ?{
? ? ? ? ?double x = points[i].x;
? ? ? ? ?double y = points[i].y;
? ? ? ? ?double x2 = x * x;
? ? ? ? ?double y2 = y * y;
? ? ? ? ?sum_x += x;
? ? ? ? ?sum_y += y;
? ? ? ? ?sum_x2 += x2;
? ? ? ? ?sum_y2 += y2;
? ? ? ? ?sum_x3 += x2 * x;
? ? ? ? ?sum_y3 += y2 * y;
? ? ? ? ?sum_xy += x * y;
? ? ? ? ?sum_x1y2 += x * y2;
? ? ? ? ?sum_x2y1 += x2 * y;
? ? ?}
? ? ?double C, D, E, G, H;
? ? ?double a, b, c;
? ? ?C = N * sum_x2 - sum_x * sum_x;
? ? ?D = N * sum_xy - sum_x * sum_y;
? ? ?E = N * sum_x3 + N * sum_x1y2 - (sum_x2 + sum_y2) * sum_x;
? ? ?G = N * sum_y2 - sum_y * sum_y;
? ? ?H = N * sum_x2y1 + N * sum_y3 - (sum_x2 + sum_y2) * sum_y;
? ? ?a = (H * D - E * G) / (C * G - D * D);
? ? ?b = (H * C - E * D) / (D * D - G * C);
? ? ?c = -(a * sum_x + b * sum_y + sum_x2 + sum_y2) / N;
? ? ?center_x = a / (-2);
? ? ?center_y = b / (-2);
? ? ?radius = sqrt(a * a + b * b - 4 * c) / 2;
? ? ?return true;
}
//-----輪廓排序-----------//
void contourSort(vector<vector<Point>>& contours)
{
?? ?vector<Point> temp;
?? ?if(!contours.empty())
?? ?{
?? ??? ?temp = contours[0];
?? ??? ?for(int i = 0;i < contours.size();i++)
?? ??? ?{
?? ??? ??? ?for(int j = contours.size()-1;j > i;j--)
?? ??? ??? ?{
?? ??? ??? ??? ?if(contours[j].size() > contours[j-1].size())
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?temp = contours[j-1];
?? ??? ??? ??? ??? ?contours[j-1] = contours[j];
?? ??? ??? ??? ??? ?contours[j] = temp;
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
?? ?}
}
//顯示提取的感興趣區(qū)域原始圖
void showImg(const vector<Mat>& Img)
{
?? ?if(Img.empty())
?? ??? ?return;
?? ?for(int i = 0;i<Img.size();i++)
?? ?{
?? ??? ?String str;
?? ??? ?String str1 = "透氣膜";
?? ??? ?char str2[2] = "";
?? ??? ?itoa(i+1,str2,10);
?? ??? ?str = str1 + str2;
?? ??? ?imshow(str,Img[i]);
?? ?}
}
//畫出處理后的結(jié)果圖
void paintProcessedImg(char* img,char* img1,MemDetectResult memdr,const vector<vector<Point>> badspots,const int leavCenter[],int result[][10],vector<vector<Point2f>> roRect)
{
?? ?Mat srcImg(Size(dst_height,dst_width),CV_8UC1,img);
?? ?Mat srcImg1(Size(dst_height,dst_width),CV_8UC1,img1);
?? ?/*imshow("原圖",srcImg);
?? ?waitKey(0);*/
?? ?if(!memdr.bwspot.empty())//如果有黑白點(diǎn)
?? ?{
?? ??? ?for(int i = 0;i<memdr.bwspot.size();i++)
?? ??? ?{
?? ??? ??? ?for(int j = 0;j<memdr.bwspot[i].size();j++)
?? ??? ??? ?{
?? ??? ??? ??? ?circle(srcImg,memdr.bwspot[i][j],0,Scalar(255,255,255),-1);
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?if(!badspots.empty())//如果有外輪廓臟點(diǎn)
?? ?{
?? ??? ?for(int i = 0;i<badspots.size();i++)
?? ??? ?{
?? ??? ??? ?for(int j = 0;j<badspots[i].size();j++)
?? ??? ??? ?{
?? ??? ??? ??? ?circle(srcImg,badspots[i][j],0,Scalar(255,255,255),-1);
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?if(!memdr.slik.empty())//如果有毛絲
?? ?{
?? ??? ?for(int i = 0;i<memdr.slik.size();i++)
?? ??? ?{
?? ??? ??? ?circle(srcImg,memdr.slik[i],0,Scalar(255,255,255),-1);
?? ??? ?}
?? ?}
?? ?if(!memdr.crease.empty())//如果有黑白點(diǎn)
?? ?{
?? ??? ?for(int i = 0;i<memdr.crease.size();i++)
?? ??? ?{
?? ??? ??? ?for(int j = 0;j<memdr.crease[i].size();j++)
?? ??? ??? ?{
?? ??? ??? ??? ?circle(srcImg,memdr.crease[i][j],0,Scalar(255,255,255),-1);
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?if(!memdr.drub.empty())//如果有復(fù)偏
?? ?{
?? ??? ?for(int i = 0;i<memdr.drub.size();i++)
?? ??? ?{
?? ??? ??? ?for(int j = 0;j<memdr.drub[i].size();j++)
?? ??? ??? ?{
?? ??? ??? ??? ?circle(srcImg,memdr.drub[i][j],0,Scalar(255,255,255),-1);
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?int height = 0;
?? ?if(leavCenter[0] == 1)//向上偏心
?? ?{
?? ??? ?height+=50;
?? ??? ?putText(srcImg,"up leave",Point(250,height),CV_FONT_ITALIC,1,Scalar(255,255,255));
?? ?}
?? ?if(leavCenter[1] == 1)//向左或向右偏心
?? ?{
?? ??? ?height+=50;
?? ??? ?putText(srcImg,"left or right leave",Point(250,height),CV_FONT_ITALIC,1,Scalar(255,255,255));
?? ?}
?? ?if(leavCenter[2] == 1)//向下偏心
?? ?{
?? ??? ?height+=50;
?? ??? ?putText(srcImg,"down leave",Point(250,height),CV_FONT_ITALIC,1,Scalar(255,255,255));
?? ?}
?? ?for(int i = 0;i<4;i++)
?? ?{
?? ??? ?if(i == 0)
?? ??? ?{
?? ??? ??? ?if(result[i][0] == -1)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"wuyangben",Point(250,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ??? ?continue;
?? ??? ??? ?}
?? ??? ??? ?if(result[i][0] == -2)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"touqimoyiwei",Point(250,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ??? ?continue;
?? ??? ??? ?}
?? ??? ??? ?if(result[i][0] == -3)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"wutouqimo",Point(250,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ??? ?continue;
?? ??? ??? ?}?? ?
?? ??? ??? ?if(result[i][4] == 1)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"quekong",Point(250,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ?}
?? ??? ?}
?? ??? ?if(i == 1)
?? ??? ?{
?? ??? ??? ?height = 0;
?? ??? ??? ?if(result[i][0] == -1)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"wuyangben",Point(1476,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ??? ?continue;
?? ??? ??? ?}
?? ??? ??? ?if(result[i][0] == -2)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"touqimoyiwei",Point(1476,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ??? ?continue;
?? ??? ??? ?}
?? ??? ??? ?if(result[i][0] == -3)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"wutouqimo",Point(1476,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ??? ?continue;
?? ??? ??? ?}?? ?
?? ??? ??? ?if(result[i][4] == 1)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"quekong",Point(1476,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ?}
?? ??? ?}
?? ??? ?
?? ??? ?if(i == 2)
?? ??? ?{
?? ??? ??? ?height = 1028;
?? ??? ??? ?if(result[i][0] == -1)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"wuyangben",Point(250,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ??? ?continue;
?? ??? ??? ?}
?? ??? ??? ?if(result[i][0] == -2)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"touqimoyiwei",Point(250,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ??? ?continue;
?? ??? ??? ?}
?? ??? ??? ?if(result[i][0] == -3)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"wutouqimo",Point(250,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ??? ?continue;
?? ??? ??? ?}?? ?
?? ??? ??? ?if(result[i][4] == 1)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"quekong",Point(250,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ?}
?? ??? ?}
?? ??? ?if(i == 3)
?? ??? ?{
?? ??? ??? ?height = 1028;
?? ??? ??? ?if(result[i][0] == -1)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"wuyangben",Point(1476,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ??? ?continue;
?? ??? ??? ?}
?? ??? ??? ?if(result[i][0] == -2)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"touqimoyiwei",Point(1476,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ??? ?continue;
?? ??? ??? ?}
?? ??? ??? ?if(result[i][0] == -3)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"wutouqimo",Point(1476,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ??? ?continue;
?? ??? ??? ?}?? ?
?? ??? ??? ?if(result[i][4] == 1)
?? ??? ??? ?{
?? ??? ??? ??? ?height+=50;
?? ??? ??? ??? ?putText(srcImg,"quekong",Point(1476,height),CV_FONT_ITALIC,1,Scalar(0,0,0));
?? ??? ??? ?}
?? ??? ?}
?? ?
?? ?}
?? ?for(int i = 0;i<roRect.size();i++)
?? ?{
?? ??? ?Point pt1 = roRect[i][0];
?? ??? ?Point pt2 = roRect[i][1];
?? ??? ?Point pt3 = roRect[i][2];
?? ??? ?Point pt4 = roRect[i][3];
?? ??? ?line(srcImg1,pt1,pt2,Scalar(255,255,255));
?? ??? ?line(srcImg1,pt2,pt3,Scalar(255,255,255));
?? ??? ?line(srcImg1,pt3,pt4,Scalar(255,255,255));
?? ??? ?line(srcImg1,pt4,pt1,Scalar(255,255,255));
?? ?}
?? ?for(int i = 0;i<4;i++)
?? ?{
?? ??? ?int addX = 0,addY = 0;
?? ??? ?if(i == 1)
?? ??? ?{
?? ??? ??? ?addX = dst_height/2;
?? ??? ?}
?? ??? ?if(i == 2)
?? ??? ?{
?? ??? ??? ?addY = dst_width/2;
?? ??? ?}
?? ??? ?if(i == 3)
?? ??? ?{
?? ??? ??? ?addX = dst_height/2;
?? ??? ??? ?addY = dst_width/2;
?? ??? ?}
?? ??? ?int flag = result[i][5];
?? ??? ?if(flag == 1)?? ??? ??? ?//上移
?? ??? ?{
?? ??? ??? ?Point pt1(150+addX,50+addY);
?? ??? ??? ?Point pt2(100+addX,100+addY);
?? ??? ??? ?Point pt3(200+addX,100+addY);
?? ??? ??? ?Point pt4(150+addX,240+addY);
?? ??? ??? ?line(srcImg,pt1,pt2,Scalar(0,0,0),3);
?? ??? ??? ?line(srcImg,pt1,pt3,Scalar(0,0,0),3);
?? ??? ??? ?line(srcImg,pt1,pt4,Scalar(0,0,0),3);
?? ??? ?}
?? ??? ?if(flag == 2 && (i == 1 || i == 3))?? ??? ?//右移
?? ??? ?{
?? ??? ??? ?Point pt1(300+addX,150+addY);
?? ??? ??? ?Point pt2(200+addX,50+addY);
?? ??? ??? ?Point pt3(200+addX,250+addY);
?? ??? ??? ?Point pt4(50+addX,150+addY);
?? ??? ??? ?line(srcImg,pt1,pt2,Scalar(0,0,0),3);
?? ??? ??? ?line(srcImg,pt1,pt3,Scalar(0,0,0),3);
?? ??? ??? ?line(srcImg,pt1,pt4,Scalar(0,0,0),3);
?? ??? ?}
?? ??? ?if(flag == 2 && (i == 0 || i == 2)) ?//左移
?? ??? ?{
?? ??? ??? ?Point pt1(200+addX,300+addY);
?? ??? ??? ?Point pt2(50+addX,200+addY);
?? ??? ??? ?Point pt3(350+addX,200+addY);
?? ??? ??? ?Point pt4(200+addX,50+addY);
?? ??? ??? ?line(srcImg,pt1,pt2,Scalar(0,0,0),3);
?? ??? ??? ?line(srcImg,pt1,pt3,Scalar(0,0,0),3);
?? ??? ??? ?line(srcImg,pt1,pt4,Scalar(0,0,0),3);
?? ??? ?}
?? ??? ?if(flag == 3)?? ??? ?//下移
?? ??? ?{
?? ??? ??? ?Point pt1(50+addX,200+addY);
?? ??? ??? ?Point pt2(150+addX,150+addY);
?? ??? ??? ?Point pt3(150+addX,250+addY);
?? ??? ??? ?Point pt4(400+addX,200+addY);
?? ??? ??? ?line(srcImg,pt1,pt2,Scalar(0,0,0),3);
?? ??? ??? ?line(srcImg,pt1,pt3,Scalar(0,0,0),3);
?? ??? ??? ?line(srcImg,pt1,pt4,Scalar(0,0,0),3);
?? ??? ?}
?? ?}
?? ?/*namedWindow("原圖1",0);
?? ?imshow("原圖1",srcImg);
?? ?waitKey(0);
?? ?namedWindow("原圖2",0);
?? ?imshow("原圖2",srcImg1);
?? ?waitKey(0);*/
}
總結(jié)
- 上一篇: 【技术+某度面经】Jenkins 内容+
- 下一篇: Day13-日历模块