#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include<opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
using namespace std;
void fillHole(const Mat srcBw, Mat &dstBw);
int main(int argc, char** argv)
{
Mat image = imread("C:/Users/think/Desktop/sole/定位孔/3.bmp");
if (image.empty()) {
cout << "could not find the image resource..." << std::endl;
return -1;
}
resize(image,image,Size(500,300));
Mat gray_image;
cvtColor(image, gray_image, CV_BGR2GRAY);
namedWindow("test image", CV_WINDOW_NORMAL);
imshow("test image", gray_image);
/*滤波处理*/
//Mat dst, dst1;
//blur(gray_image, dst, Size(3, 3), Point(-1, -1));
//namedWindow("均值滤波");
//imshow("均值滤波", dst);
//GaussianBlur(gray_image, dst, Size(5, 5), 5, 5);
//namedWindow("高斯滤波");
//imshow("高斯滤波", dst);
//medianBlur(gray_image, dst, 5);
//namedWindow("中值滤波");
//imshow("中值滤波", dst);
//bilateralFilter(gray_image, dst, 5, 100, 3);
//namedWindow("双边滤波");
//imshow("双边滤波", dst);
/*二值图像*/
Mat result;
threshold(gray_image, result, 130, 255, CV_THRESH_BINARY_INV); //可以使用trackbar的方式去调阈值
imshow("erzhi", result);
/*填洞*/
Mat fillhole;
fillHole(result, fillhole);
imshow("fillhole", fillhole);
/* 提取roi区域 */
/*提取鞋面二值图像*/
int x = 0;
int y = 0;
int largest_contour_index = 0;
//Rect bounding_rect;
int largest_area = 0;
Mat ImageContours = Mat::zeros(fillhole.size(), CV_8UC1);
Mat ImgContours = Mat::zeros(fillhole.size(), CV_8UC1);
std::vector<cv::Rect> blue_rect;
vector<vector<Point> > contours; // Vector for storing contours
vector<Vec4i> hierarchy;
findContours(fillhole, contours, hierarchy, RETR_LIST, CHAIN_APPROX_NONE); // Find the contours in the image
for (size_t i = 0; i< contours.size(); i++) // iterate through each contour.
{
double area = contourArea(contours[i]); // Find the area of contour
if (area > largest_area)
{
largest_area = area;
largest_contour_index = i; //Store the index of largest contour
}
}
for (int j = 0; j < contours[largest_contour_index].size(); j++)
{
//获取轮廓上点的坐标
Point P = Point(contours[largest_contour_index][j].x, contours[largest_contour_index][j].y);
ImgContours.at<uchar>(P) = 255;
}
drawContours(ImageContours, contours, largest_contour_index, Scalar(255), -1, 8,noArray(),2147483647,Point(1,1)); //画出了面积最大的区域
imshow("轮廓", ImageContours);
//imshow("轮廓点集合", ImgContours);
/* 对鞋面区域做roi提取*/
/*1.提取重心*/
Mat tmp(contours.at(largest_contour_index)); //这里只是画一个区域的重心,如果需要可以直接用for循环去遍历所有的区域来找所有区域的重心
Moments moment = moments(tmp, false);
if (moment.m00 != 0)//除数不能为0
{
x = cvRound(moment.m10 / moment.m00);//计算重心横坐标
y = cvRound(moment.m01 / moment.m00);//计算重心纵坐标
}
circle(ImageContours, Point(x, y), 1, Scalar(0,0,255), 1, 8);
//imshow("hua dian ", ImageContours); //记得重新开画板去显示图像
/*2.做仿射变换*/
Mat suoxiao_img;
suoxiao_img = getRotationMatrix2D(Point(x,y),0,0.95);
warpAffine(ImageContours, suoxiao_img, suoxiao_img, ImageContours.size(), INTER_LINEAR);
//imshow("suofang dian ", suoxiao_img);
/*3.相减得到感兴趣的区域*/
Mat roi_regin;
roi_regin = ImageContours - suoxiao_img;
imshow("roi region", roi_regin);
/*4.还原原来的阈值图像*/
Mat roi_image;
bitwise_and(gray_image,roi_regin, roi_image);
imshow("roi_image", roi_image);
/*5.对原来的图像做阈值处理*/
Mat yuzhi_image;
//blur(yuzhi_image, yuzhi_image,Size(3,3));
threshold(roi_image,yuzhi_image,22,253,THRESH_BINARY);
//adaptiveThreshold(roi_image, yuzhi_image,255,ADAPTIVE_THRESH_GAUSSIAN_C,THRESH_BINARY_INV,3,3);
namedWindow("yuzhi",0);
imshow("yuzhi",yuzhi_image);
/*6.形态学操作*/
/*图像置反*/
//bitwise_not(yuzhi_image, roi_image);
//imshow("qufan", roi_image);
///*腐蚀膨胀+开运算+闭运算*/
Mat erodeElement = getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3));
Mat xingtai_image;
dilate(fillhole,mat_image_dst, erodeElement); //膨胀
//erode(yuzhi_image, xingtai_image, erodeElement); //腐蚀
morphologyEx(yuzhi_image, xingtai_image, MORPH_OPEN, erodeElement, Point(-1, -1));//改变MORPH_OPEN可以变成闭运算
imshow("形态学处理", xingtai_image);
/*边缘处理*/
//Mat canny_contour;
//Canny(roi, canny_contour, 50, 200, 3);//还有Sobel和Laplance,x相应使用要求可以具体的API
//imshow("edge", canny_contour);
waitKey(0);
return 0;
}
void fillHole(const Mat srcBw, Mat &dstBw)
{
Size m_Size = srcBw.size();
Mat Temp = Mat::zeros(m_Size.height + 2, m_Size.width + 2, srcBw.type());//延展图像
srcBw.copyTo(Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)));
cv::floodFill(Temp, Point(0, 0), Scalar(255));
Mat cutImg;//裁剪延展的图像
Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)).copyTo(cutImg);
dstBw = srcBw | (~cutImg);
}
效果就是这样了