
形态学操作应用-提取水平与垂直线原理方法图像形态学操作时候可以通过自定义的结构元素实现结构元素对输入图像一些对象敏感、另外一些对象不敏感这样就会让敏感的对象改变而不敏感的对象保留输出。通过使用两个最基本的形态学操作 –膨胀与腐蚀使用不同的结构元素实现对输入图像的操作、得到想要的结果。膨胀输出的像素值是结构元素覆盖下输入图像的最大像素值腐蚀输出的像素值是结构元素覆盖下输入图像的最小像素值代码#include opencv2/opencv.hpp #include iostream using namespace cv; int main(int argc, char** argv) { Mat src imread(C:/Users/Administrator/Pictures/hello.png); if (src.empty()) { printf(不能加载图像); return -1; } namedWindow(创建成功, CV_WINDOW_AUTOSIZE); imshow(创建成功, src); Mat gray; cvtColor(src, gray, CV_BGR2GRAY); namedWindow(gray image, 1); imshow(gray image, gray); Mat binImg; adaptiveThreshold(~gray, binImg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2); imshow(binary image, binImg); waitKey(0); return 0; }图1-1 原图像灰度图像与二值图像其中代码参数Mat hline getStructuringElement(MORPH_RECT, Size(src.cols / 16, 1), Point(-1, -1));//水平结构元素 Mat vline getStructuringElement(MORPH_RECT, Size(1, src.rows / 16), Point(-1, -1));//竖直结构元素 Mat dst; Mat temp; erode(binImg, temp, hline); dilate(temp, dst, hline); bitwise_not(dst, dst); imshow(Final Result, dst);开操作后提取水平线图1-2 提取水平线开操作后提取竖直线:图1-3 提取竖直线开操作也可以用这一句morphologyEx(binImg, dst, CV_MOP_OPEN, vline);bitwise_not(dst, dst);这一句是颜色反转。应用提取验证码图1-4 效果图注意图片名称最好不要是中文。图像金字塔上采样和降采样#include opencv2/opencv.hpp #include iostream using namespace cv; int main(int argc, char** argv) { Mat src imread(C:/Users/Administrator/Pictures/20160711084909.jpg); if (src.empty()) { printf(不能加载图像); return -1; } namedWindow(input image, CV_WINDOW_AUTOSIZE); imshow(input image, src); Mat dst, dstdown; pyrUp(src, dst, Size(src.cols * 2, src.rows * 2)); imshow(output image, dst); pyrDown(src, dstdown, Size(src.cols / 2, src.rows / 2)); imshow(output2 image, dstdown); waitKey(0); return 0; }图1-5 上采样和降采样高斯不同DOGDifference Of GaussianMat gray, g1, g2, dogImg; cvtColor(src, gray, CV_BGR2GRAY); GaussianBlur(gray, g1, Size(3, 3), 0, 0); GaussianBlur(g1, g2, Size(3, 3), 0, 0); subtract(g1, g2, dogImg, Mat()); imshow(dogImg, dogImg); waitKey(0); return 0; }此时可以看到一点微弱的轮廓是因为图像变化后不明显。图1-6 不明显的高斯不同图此时加入normalize(dogImg, dogImg, 255, 0, NORM_MINMAX);将图像在0-255的地方归一化如图所示图1-7 归一化后的高斯不同图完整代码如下#include opencv2/opencv.hpp #include iostream using namespace cv; int main(int argc, char** argv) { Mat src imread(C:/Users/Administrator/Pictures/20160711084909.jpg); if (src.empty()) { printf(不能加载图像); return -1; } namedWindow(input image, CV_WINDOW_AUTOSIZE); imshow(input image, src); Mat dst, dstdown; //上采样 pyrUp(src, dst, Size(src.cols * 2, src.rows * 2)); imshow(output image, dst); //降采用 pyrDown(src, dstdown, Size(src.cols / 2, src.rows / 2)); imshow(output2 image, dstdown); //DOG Mat gray, g1, g2, dogImg; cvtColor(src, gray, CV_BGR2GRAY); GaussianBlur(gray, g1, Size(5, 5), 0, 0); GaussianBlur(g1, g2, Size(5, 5), 0, 0); subtract(g1, g2, dogImg, Mat()); //归一化显示 normalize(dogImg, dogImg, 255, 0, NORM_MINMAX); imshow(dogImg, dogImg); waitKey(0); return 0; }基本阈值操作分割类型超过阈值的就和阈值取相等。小于阈值的取0.大于阈值取0.寻找阈值的方法二值化阈值代码#include opencv2/opencv.hpp #include iostream using namespace cv; int threshold_value 127; int threshold_max 255; Mat src, dst; const char* output_title binary image; void Threshold_Demo(int, void*); int main(int argc, char** argv) { src imread(C:/Users/Administrator/Pictures/20160711084909.jpg); if (src.empty()) { printf(不能加载图像); return -1; } namedWindow(input image, CV_WINDOW_AUTOSIZE); namedWindow(output_title, CV_WINDOW_AUTOSIZE); imshow(input image, src); createTrackbar(Threshold Value, output_title, threshold_value, threshold_max, Threshold_Demo); Threshold_Demo(0, 0); waitKey(0); return 0; } void Threshold_Demo(int, void*) { Mat gray; cvtColor(src, gray, CV_BGR2GRAY); threshold(gray, dst, threshold_value, threshold_max, THRESH_BINARY);//二值化阈值 imshow(output_title, dst); }图1-8 二值化阈值注意如果需要生成动态调节结构元素的控制条必须要先创建namedwindow这个窗口如果直接imshow是不会生成控制条的。反向二值化阈值threshold(gray, dst, threshold_value, threshold_max, THRESH_BINARY_INV);图1-9 反向二值化阈值这五种操作可以新建一个trackbar统一起来用type_value来代表五种不同的操作。效果如下图1-10 五种操作集合代码#include opencv2/opencv.hpp #include iostream using namespace cv; int threshold_value 127; int threshold_max 255; int type_value 2; int type_max 4; Mat src, dst; const char* output_title binary image; void Threshold_Demo(int, void*); int main(int argc, char** argv) { src imread(C:/Users/Administrator/Pictures/20160711084909.jpg); if (src.empty()) { printf(不能加载图像); return -1; } namedWindow(input image, CV_WINDOW_AUTOSIZE); namedWindow(output_title, CV_WINDOW_AUTOSIZE); imshow(input image, src); createTrackbar(Threshold Value, output_title, threshold_value, threshold_max, Threshold_Demo); createTrackbar(Type Value, output_title, type_value, type_max, Threshold_Demo);//这个trackbar可以改变type_value的值 Threshold_Demo(0, 0); waitKey(0); return 0; } void Threshold_Demo(int, void*) { Mat gray; cvtColor(src, gray, CV_BGR2GRAY); //threshold(gray, dst, threshold_value, threshold_max, THRESH_BINARY);//二值化阈值 //threshold(gray, dst, threshold_value, threshold_max, THRESH_BINARY_INV);//反向二值化阈值 threshold(gray, dst, threshold_value, threshold_max, type_value); imshow(output_title, dst); }threshold(gray, dst, 0, 255,THRESH_OTSU | type_value);//自动计算阈值或者threshold(gray, dst, 0, 255, THRESH_TRIANGLE | type_value);//自动计算阈值直方这个操作可以自动计算阈值将原代码中 threshold(gray, dst, threshold_value, threshold_max, type_value);替换即可。PS:灰度图像才能进行阈值操作。