由于项目的需要提取图像之中的一个接近于竖直的物体,一般的方法是进行图像分割,分割方式使用什么OTSU方式以及hsv方法等等。但是项目中使用的相机是黑白相机,会受到一定的限制。因此想到的是使用线条提取方式。线条提取方式之中最好的方法是使用canny算法,但是这里不能够将接近竖直特征进行提取,因此,此处使用了Prewitt算子进行提取,但是只用这个算法,轮廓提取不出来,就结合了一下canny算子。下面是我的思路,感觉实现过程比较麻烦,但是居然实现了[苦笑]!!!!
本次测试的案例是使用校门口的一个图片,图中存在很多的干扰,如下图所示
-
#include <opencv2/opencv.hpp>
-
#include <opencv2/highgui/highgui.hpp>
-
#include <iostream>
-
#include <opencv2/core.hpp>
-
#include <opencv2/highgui.hpp>
-
#include <opencv2/imgproc.hpp>
-
using
namespace cv;
-
using
namespace std;
-
-
-
void getPrewitt_oper(cv::Mat& getPrewitt_horizontal, cv::Mat& getPrewitt_vertical, cv::Mat& getPrewitt_Diagonal1, cv::Mat& getPrewitt_Diagonal2) {
-
//水平方向
-
getPrewitt_horizontal = (cv::
Mat_<
float>(
3,
3) <<
-1,
-1,
-1,
0,
0,
0,
1,
1,
1);
-
//垂直方向
-
getPrewitt_vertical = (cv::
Mat_<
float>(
3,
3) <<
-1,
0,
1,
-1,
0,
1,
-1,
0,
1);
-
//对角135°
-
getPrewitt_Diagonal1 = (cv::
Mat_<
float>(
3,
3) <<
0,
1,
1,
-1,
0,
1,
-1,
-1,
0);
-
//对角45°
-
getPrewitt_Diagonal2 = (cv::
Mat_<
float>(
3,
3) <<
-1,
-1,
0,
-1,
0,
1,
0,
1,
1);
-
-
//逆时针反转180°得到卷积核
-
cv::
flip(getPrewitt_horizontal, getPrewitt_horizontal,
-1);
-
cv::
flip(getPrewitt_vertical, getPrewitt_vertical,
-1);
-
cv::
flip(getPrewitt_Diagonal1, getPrewitt_Diagonal1,
-1);
-
cv::
flip(getPrewitt_Diagonal2, getPrewitt_Diagonal2,
-1);
-
}
-
-
void edge_Prewitt(cv::Mat& src, cv::Mat& dst1, cv::Mat& dst2, cv::Mat& dst3, cv::Mat& dst4, cv::Mat& dst, int ddepth, double delta = 0, int borderType = cv::BORDER_DEFAULT) {
-
//获取Prewitt算子
-
cv::Mat getPrewitt_horizontal;
-
cv::Mat getPrewitt_vertical;
-
cv::Mat getPrewitt_Diagonal1;
-
cv::Mat getPrewitt_Diagonal2;
-
getPrewitt_oper(getPrewitt_horizontal, getPrewitt_vertical, getPrewitt_Diagonal1, getPrewitt_Diagonal2);
-
-
//卷积得到水平方向边缘
-
cv::
filter2D(src, dst1, ddepth, getPrewitt_horizontal, cv::
Point(
-1,
-1), delta, borderType);
-
-
//卷积得到4垂直方向边缘
-
cv::
filter2D(src, dst2, ddepth, getPrewitt_vertical, cv::
Point(
-1,
-1), delta, borderType);
-
-
//卷积得到45°方向边缘
-
cv::
filter2D(src, dst3, ddepth, getPrewitt_Diagonal1, cv::
Point(
-1,
-1), delta, borderType);
-
-
//卷积得到135°方向边缘
-
cv::
filter2D(src, dst4, ddepth, getPrewitt_Diagonal2, cv::
Point(
-1,
-1), delta, borderType);
-
-
//边缘强度(近似)
-
cv::
convertScaleAbs(dst1, dst1);
//求绝对值并转为无符号8位图
-
cv::
convertScaleAbs(dst2, dst2);
-
-
cv::
convertScaleAbs(dst3, dst3);
//求绝对值并转为无符号8位图
-
cv::
convertScaleAbs(dst4, dst4);
-
dst = dst1 + dst2;
-
-
}
-
-
//数组从大到小排序
-
void reserve(int x[], int n) {
-
int i, j, temp;
-
for (i =
0; i < n -
1; i++) {
//一共n个元素,则需要比较n-1次
-
for (j =
0; j < n -
1 - i; j++) {
//每一个元素需要比较的次数
-
if (x[i] < x[i + j +
1]) {
-
temp = x[i];
-
x[i] = x[i + j +
1];
-
x[i + j +
1] = temp;
-
}
-
}
-
}
-
}
-
-
-
-
int main()
-
{
-
cv::Mat src = cv::
imread(
"楼.jpg");
-
if (src.
empty()) {
-
return
-1;
-
}
-
cout <<
"??" << endl;
-
if (src.
channels() >
1) cv::
cvtColor(src, src, CV_RGB2GRAY);
-
cv::Mat dst, dst1, dst2, dst3, dst4, dst5;
-
-
Mat src1 = cv::
imread(
"楼.jpg");
-
Mat src2 = cv::
imread(
"楼.jpg");
-
-
//medianBlur(src, src, 5); //均值滤波
-
GaussianBlur(src, src,
Size(
5,
5),
0);
//高斯滤波
-
cout <<
"??" << endl;
-
-
//注意:要采用CV_32F,因为有些地方卷积后为负数,若用8位无符号,则会导致这些地方为0
-
edge_Prewitt(src, dst1, dst2, dst3, dst4, dst, CV_32F);
-
-
cv::
namedWindow(
"垂直边缘", CV_WINDOW_NORMAL);
-
imshow(
"垂直边缘", dst2);
-
cout <<
"??" << endl;
-
-
-
-
//获取结构
-
cv::Mat element1 = cv::
getStructuringElement(cv::MORPH_RECT, cv::
Size(
3,
3));
-
-
Mat out1;
-
//进行形态学开运算操作
-
morphologyEx(dst2, out1, MORPH_OPEN, element1);
//形态学开运算
-
cv::
namedWindow(
"xingtai", CV_WINDOW_NORMAL);
-
imshow(
"xingtai", out1);
-
-
-
-
-
//第二次进行形态学操作
-
edge_Prewitt(dst2, dst1, out1, dst3, dst4, dst, CV_32F);
-
cv::
namedWindow(
"垂直边缘1", CV_WINDOW_NORMAL);
-
imshow(
"垂直边缘1", out1);
-
cout <<
"??" << endl;
-
-
morphologyEx(out1, out1, MORPH_OPEN, element1);
//形态学开运算
-
cv::
namedWindow(
"xingtai1", CV_WINDOW_NORMAL);
-
imshow(
"xingtai1", out1);
-
-
-
//获取结构
-
cv::Mat element2 = cv::
getStructuringElement(cv::MORPH_ELLIPSE, cv::
Size(
10,
10));
-
-
Mat out2;
-
//进行形态学闭运算操作
-
morphologyEx(out1, out2, MORPH_CLOSE, element2);
//形态学开运算
-
cv::
namedWindow(
"xingtai2", CV_WINDOW_NORMAL);
-
imshow(
"xingtai2", out2);
-
imwrite(
"xingtai2.jpg", out2);
-
-
/*
-
//膨胀运算,将细小缝隙填补上,非必要
-
Mat kernel = getStructuringElement(0, Size(3, 3));
-
dilate(out2, dst2, kernel);
-
cv::namedWindow("膨胀", CV_WINDOW_NORMAL);
-
imshow("膨胀", dst2);
-
*/
-
-
cv::
threshold(out2, dst2,
5,
255, cv::THRESH_BINARY);
-
cv::
namedWindow(
"二值化", CV_WINDOW_NORMAL);
-
imshow(
"二值化", dst2);
-
-
cv::
threshold(dst2, dst2,
5,
255, cv::THRESH_BINARY_INV);
-
cv::
namedWindow(
"反二值化", CV_WINDOW_NORMAL);
-
imshow(
"反二值化", dst2);
-
-
-
//进行形态学闭运算操作
-
morphologyEx(dst2, out2, MORPH_CLOSE, element2);
//形态学开运算
-
cv::
namedWindow(
"xingtai3", CV_WINDOW_NORMAL);
-
imshow(
"xingtai3", out2);
-
imwrite(
"xingtai3.jpg", out2);
-
-
/*
-
cv::threshold(dst2, dst2, 5, 255, cv::THRESH_BINARY);
-
cv::namedWindow("反二值化", CV_WINDOW_NORMAL);
-
imshow("反二值化", dst2);
-
imwrite("反二值化.jpg", dst2);
-
*/
-
-
/*
-
//膨胀运算,将细小缝隙填补上,非必要
-
Mat kernel = getStructuringElement(0, Size(5, 5));
-
dilate(out2, out2, kernel);
-
cv::namedWindow("膨胀1", CV_WINDOW_NORMAL);
-
imshow("膨胀1", out2);*/
-
-
Canny(out2, dst2,
5,
10);
-
cv::
namedWindow(
"Canny", CV_WINDOW_NORMAL);
-
imshow(
"Canny", dst2);
-
imwrite(
"Canny.jpg", dst2);
-
-
-
vector<Vec4i> lines;
-
HoughLinesP(dst2, lines,
1, CV_PI /
180,
50,
200,
30);
-
int Length[
100] = {
0};
//存放直线长度
-
for (
size_t i =
0; i < lines.
size(); i++)
-
{
-
Vec4i I = lines[i];
-
double x1 = I[
0];
-
double y1 = I[
1];
-
double x2 = I[
2];
-
double y2 = I[
3];
-
-
//筛选满足条件的点
-
if (
abs(x1 - x2) +
abs(y1 - y2) >
50)
-
{
-
Length[i] =
sqrt( (x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2));
-
//将满足条件的点画出
-
line(src1,
Point2d(x1, y1),
Point2d(x2, y2),
Scalar(
0,
255,
255),
2);
-
-
cout <<
" " <<
"(" << x1 <<
"," << y1 <<
")" <<
" " <<
"(" << x2 <<
"," << y2 <<
")" << endl;
-
//line(canny, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
-
}
-
}
-
-
Mat imgShow;
-
imgShow = src1;
-
resize(imgShow, imgShow,
Size(imgShow.cols /
4, imgShow.rows /
4));
-
imshow(
"imgShow", imgShow);
-
imwrite(
"shuchu.png", src1);
-
-
-
reserve(Length,
100);
-
for (
int i =
0; i <
100; i++) {
-
cout <<
"长度"<<Length[i] << endl;
//输出排序后的数组元素
-
}
-
-
for (
size_t i =
0; i < lines.
size(); i++)
-
{
-
Vec4i I = lines[i];
-
double x1 = I[
0];
-
double y1 = I[
1];
-
double x2 = I[
2];
-
double y2 = I[
3];
-
cout <<
"sdjk" << endl;
-
cout <<
int(
sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) << endl;
-
//筛选满足条件的点
-
if ((
int(
sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) == Length[
0] ) || (
int(
sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) == Length[
1]))
-
{
-
-
//将满足条件的点画出
-
line(src2,
Point2d(x1, y1),
Point2d(x2, y2),
Scalar(
0,
255,
255),
2);
-
-
cout <<
"djfkljsa " <<
"(" << x1 <<
"," << y1 <<
")" <<
" " <<
"(" << x2 <<
"," << y2 <<
")" << endl;
-
//line(canny, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
-
}
-
}
-
-
imgShow = src2;
-
resize(imgShow, imgShow,
Size(imgShow.cols /
4, imgShow.rows /
4));
-
imshow(
"imgShow2", imgShow);
-
imwrite(
"shuchu2.png", src2);
-
-
-
-
-
-
waitKey(
0);
-
return
0;
-
}
调试过程:本次在进行调试过程之中进行了两次垂直检测迭代,进一步去排除水平线的干扰.使用形态学操作去除图片之中的空洞等等.
第一次进行垂直检测,注意这个地方只能够用特定的算子进行垂直检测,别的算子没有这个效果.
为了减少图片之中白色空洞的干扰,使用开操作.
重复上述操作,进一步排除水平线的干扰.
接下来是进行闭操作,将图中的白色线条尽可能连在一起,上图之中的楼左侧的线有一些断开了.
闭操作的缺陷是会产生小白点点.如下二值化过程
再进行一次反二值化,因为我不会用别的算子结合霍夫直线检测检测出来直线,只能转回去进行操作.
形态学操作,去除白点
canny一下检测出来轮廓
显示全部直线
直线提取,我的方式是提取最长的两段直线。
在上述操作完成之后,得到了物体的粗定位直线。
但是上面的算法还是存在相应的问题,换了一个别的图像可能就检测的不准。发现问题就是出在了二值化的过程。
为了修正上方的算法的失败,使用提取外部轮廓的方式进行求取,将代码改了改。
-
#include <opencv2/opencv.hpp>
-
#include <opencv2/highgui/highgui.hpp>
-
#include <iostream>
-
#include <opencv2/core.hpp>
-
#include <opencv2/highgui.hpp>
-
#include <opencv2/imgproc.hpp>
-
using
namespace cv;
-
using
namespace std;
-
-
-
void getPrewitt_oper(cv::Mat& getPrewitt_horizontal, cv::Mat& getPrewitt_vertical, cv::Mat& getPrewitt_Diagonal1, cv::Mat& getPrewitt_Diagonal2) {
-
//水平方向
-
getPrewitt_horizontal = (cv::
Mat_<
float>(
3,
3) <<
-1,
-1,
-1,
0,
0,
0,
1,
1,
1);
-
//垂直方向
-
getPrewitt_vertical = (cv::
Mat_<
float>(
3,
3) <<
-1,
0,
1,
-1,
0,
1,
-1,
0,
1);
-
//对角135°
-
getPrewitt_Diagonal1 = (cv::
Mat_<
float>(
3,
3) <<
0,
1,
1,
-1,
0,
1,
-1,
-1,
0);
-
//对角45°
-
getPrewitt_Diagonal2 = (cv::
Mat_<
float>(
3,
3) <<
-1,
-1,
0,
-1,
0,
1,
0,
1,
1);
-
-
//逆时针反转180°得到卷积核
-
cv::
flip(getPrewitt_horizontal, getPrewitt_horizontal,
-1);
-
cv::
flip(getPrewitt_vertical, getPrewitt_vertical,
-1);
-
cv::
flip(getPrewitt_Diagonal1, getPrewitt_Diagonal1,
-1);
-
cv::
flip(getPrewitt_Diagonal2, getPrewitt_Diagonal2,
-1);
-
}
-
-
void edge_Prewitt(cv::Mat& src, cv::Mat& dst1, cv::Mat& dst2, cv::Mat& dst3, cv::Mat& dst4, cv::Mat& dst, int ddepth, double delta = 0, int borderType = cv::BORDER_DEFAULT) {
-
//获取Prewitt算子
-
cv::Mat getPrewitt_horizontal;
-
cv::Mat getPrewitt_vertical;
-
cv::Mat getPrewitt_Diagonal1;
-
cv::Mat getPrewitt_Diagonal2;
-
getPrewitt_oper(getPrewitt_horizontal, getPrewitt_vertical, getPrewitt_Diagonal1, getPrewitt_Diagonal2);
-
-
//卷积得到水平方向边缘
-
cv::
filter2D(src, dst1, ddepth, getPrewitt_horizontal, cv::
Point(
-1,
-1), delta, borderType);
-
-
//卷积得到4垂直方向边缘
-
cv::
filter2D(src, dst2, ddepth, getPrewitt_vertical, cv::
Point(
-1,
-1), delta, borderType);
-
-
//卷积得到45°方向边缘
-
cv::
filter2D(src, dst3, ddepth, getPrewitt_Diagonal1, cv::
Point(
-1,
-1), delta, borderType);
-
-
//卷积得到135°方向边缘
-
cv::
filter2D(src, dst4, ddepth, getPrewitt_Diagonal2, cv::
Point(
-1,
-1), delta, borderType);
-
-
//边缘强度(近似)
-
cv::
convertScaleAbs(dst1, dst1);
//求绝对值并转为无符号8位图
-
cv::
convertScaleAbs(dst2, dst2);
-
-
cv::
convertScaleAbs(dst3, dst3);
//求绝对值并转为无符号8位图
-
cv::
convertScaleAbs(dst4, dst4);
-
dst = dst1 + dst2;
-
-
}
-
-
//数组从大到小排序
-
void reserve(int x[], int n) {
-
int i, j, temp;
-
for (i =
0; i < n -
1; i++) {
//一共n个元素,则需要比较n-1次
-
for (j =
0; j < n -
1 - i; j++) {
//每一个元素需要比较的次数
-
if (x[i] < x[i + j +
1]) {
-
temp = x[i];
-
x[i] = x[i + j +
1];
-
x[i + j +
1] = temp;
-
}
-
}
-
}
-
}
-
-
-
-
int main()
-
{
-
cv::Mat src = cv::
imread(
"楼.jpg");
-
if (src.
empty()) {
-
return
-1;
-
}
-
cout <<
"??" << endl;
-
if (src.
channels() >
1) cv::
cvtColor(src, src, CV_RGB2GRAY);
-
cv::Mat dst, dst1, dst2, dst3, dst4, dst5;
-
-
Mat src1 = cv::
imread(
"楼.jpg");
-
Mat src2 = cv::
imread(
"楼.jpg");
-
-
//medianBlur(src, src, 5); //均值滤波
-
GaussianBlur(src, src,
Size(
5,
5),
0);
//高斯滤波
-
cout <<
"??" << endl;
-
-
//注意:要采用CV_32F,因为有些地方卷积后为负数,若用8位无符号,则会导致这些地方为0
-
edge_Prewitt(src, dst1, dst2, dst3, dst4, dst, CV_32F);
-
-
cv::
namedWindow(
"垂直边缘", CV_WINDOW_NORMAL);
-
imshow(
"垂直边缘", dst2);
-
cout <<
"??" << endl;
-
-
-
-
/*
-
Mat shdjk;
-
cv::threshold(dst2, shdjk, 25, 255, cv::THRESH_BINARY);
-
cv::namedWindow("二值化1212", CV_WINDOW_NORMAL);
-
imshow("二值化1212", shdjk);
-
*/
-
-
//获取结构
-
cv::Mat element1 = cv::
getStructuringElement(cv::MORPH_RECT, cv::
Size(
3,
3));
-
-
Mat out1;
-
//进行形态学开运算操作
-
morphologyEx(dst2, out1, MORPH_OPEN, element1);
//形态学开运算
-
cv::
namedWindow(
"xingtai", CV_WINDOW_NORMAL);
-
imshow(
"xingtai", out1);
-
-
-
Mat out2;
-
//第二次进行形态学操作
-
edge_Prewitt(out1, dst1, out1, dst3, dst4, dst, CV_32F);
-
cv::
namedWindow(
"垂直边缘1", CV_WINDOW_NORMAL);
-
imshow(
"垂直边缘1", out1);
-
cout <<
"??" << endl;
-
-
-
/*
-
morphologyEx(out1, out1, MORPH_OPEN, element1);//形态学开运算
-
cv::namedWindow("xingtai1", CV_WINDOW_NORMAL);
-
imshow("xingtai1", out1);
-
-
//获取结构
-
cv::Mat element2 = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(10, 10));
-
-
-
//进行形态学闭运算操作
-
morphologyEx(out1, out2, MORPH_CLOSE, element2);//形态学闭合运算
-
cv::namedWindow("xingtai2", CV_WINDOW_NORMAL);
-
imshow("xingtai2", out2);
-
imwrite("xingtai2.jpg", out2);
-
-
waitKey(0);
-
*/
-
std::vector<std::vector<cv::Point>> contours;
-
std::vector<cv::Vec4i> hierarchy;
-
findContours(out1, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
-
double maxArea =
0;
-
int index =
0;
-
vector<cv::Point> maxContour;
-
for (
size_t i =
0; i < contours.
size(); i++)
-
{
-
double area = cv::
contourArea(contours[i]);
-
if (area > maxArea)
-
{
-
maxArea = area;
-
maxContour = contours[i];
-
index = i;
-
}
-
}
-
drawContours(src1, contours, index,
Scalar(
255));
// 参数
-
cv::
namedWindow(
"test", CV_WINDOW_NORMAL);
-
imshow(
"test", src1);
-
waitKey(
0);
-
/*
-
Mat shdjk;
-
cv::threshold(out1, shdjk, 10, 255, cv::THRESH_BINARY);
-
cv::namedWindow("二值化1212", CV_WINDOW_NORMAL);
-
imshow("二值化1212", shdjk);
-
-
std::vector<std::vector<cv::Point>> contours;
-
std::vector<cv::Vec4i> hierarchy;
-
cv::findContours(shdjk, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); //只找最外层轮廓
-
-
-
std::vector<std::vector<cv::Point>> approxCurves(contours.size());
-
for (int i = 0; i < contours.size(); ++i) { //绘制逼近后的轮廓
-
double epsilon = 0.1 * cv::arcLength(contours[i], true);
-
cv::approxPolyDP(contours[i], approxCurves[i], epsilon, true);
-
-
cv::drawContours(src1, approxCurves, i, cv::Scalar(0, 255, 0), 2);
-
}
-
cv::namedWindow("success", CV_WINDOW_NORMAL);
-
imshow("success", src1);
-
-
cv::waitKey();
-
-
*/
-
-
-
-
-
-
//
-
/*
-
Mat dhfjua;
-
cv::threshold(out2, dhfjua, 15, 255, cv::THRESH_BINARY);
-
cv::namedWindow("二值化000", CV_WINDOW_NORMAL);
-
imshow("二值化000", dhfjua);
-
*/
-
/*
-
//膨胀运算,将细小缝隙填补上,非必要
-
Mat kernel = getStructuringElement(0, Size(3, 3));
-
dilate(out2, dst2, kernel);
-
cv::namedWindow("膨胀", CV_WINDOW_NORMAL);
-
imshow("膨胀", dst2);
-
*/
-
/*0
-
cv::threshold(out2, dst2, 5, 255, cv::THRESH_BINARY);
-
cv::namedWindow("二值化", CV_WINDOW_NORMAL);
-
imshow("二值化", dst2);
-
-
cv::threshold(dst2, dst2, 5, 255, cv::THRESH_BINARY_INV);
-
cv::namedWindow("反二值化", CV_WINDOW_NORMAL);
-
imshow("反二值化", dst2);
-
*/
-
/*
-
Mat out3;
-
//进行形态学闭运算操作
-
morphologyEx(dst2, out3, MORPH_CLOSE, element2);//形态学开运算
-
cv::namedWindow("xingtai3", CV_WINDOW_NORMAL);
-
imshow("xingtai3", out3);
-
imwrite("xingtai3.jpg", out3);
-
*/
-
-
waitKey(
0);
-
vector<Vec4i> lines;
-
HoughLinesP(src1, lines,
1, CV_PI /
180,
100,
400,
30);
-
int Length[
1000] = {
0 };
//存放直线长度
-
for (
size_t i =
0; i < lines.
size(); i++)
-
{
-
Vec4i I = lines[i];
-
double x1 = I[
0];
-
double y1 = I[
1];
-
double x2 = I[
2];
-
double y2 = I[
3];
-
-
//筛选满足条件的点
-
if (
abs(x1 - x2) +
abs(y1 - y2) >
50)
-
{
-
Length[i] =
sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2));
-
//将满足条件的点画出
-
line(src1,
Point2d(x1, y1),
Point2d(x2, y2),
Scalar(
0,
255,
255),
2);
-
-
cout <<
" " <<
"(" << x1 <<
"," << y1 <<
")" <<
" " <<
"(" << x2 <<
"," << y2 <<
")" << endl;
-
//line(canny, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
-
}
-
}
-
-
-
-
Mat imgShow;
-
imgShow = src1;
-
resize(imgShow, imgShow,
Size(imgShow.cols /
4, imgShow.rows /
4));
-
imshow(
"imgShow", imgShow);
-
imwrite(
"shuchu.png", src1);
-
-
-
reserve(Length,
1000);
-
for (
int i =
0; i <
1000; i++) {
-
cout <<
"长度" << Length[i] << endl;
//输出排序后的数组元素
-
}
-
-
for (
size_t i =
0; i < lines.
size(); i++)
-
{
-
Vec4i I = lines[i];
-
double x1 = I[
0];
-
double y1 = I[
1];
-
double x2 = I[
2];
-
double y2 = I[
3];
-
cout <<
"sdjk" << endl;
-
cout <<
int(
sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) << endl;
-
//筛选满足条件的点
-
if ((
int(
sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) == Length[
0]) || (
int(
sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) == Length[
1]))
-
{
-
-
//将满足条件的点画出
-
line(src2,
Point2d(x1, y1),
Point2d(x2, y2),
Scalar(
0,
255,
255),
2);
-
-
cout <<
"djfkljsa " <<
"(" << x1 <<
"," << y1 <<
")" <<
" " <<
"(" << x2 <<
"," << y2 <<
")" << endl;
-
//line(canny, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
-
}
-
}
-
-
imgShow = src2;
-
resize(imgShow, imgShow,
Size(imgShow.cols /
4, imgShow.rows /
4));
-
imshow(
"imgShow2", imgShow);
-
imwrite(
"shuchu2.png", src2);
-
-
-
-
-
-
waitKey(
0);
-
return
0;
-
}
效果还是不好,问题就是出在了相应的一个二值化的过程,因此,想到使用区域增长算法改进
-
#include <iostream>
-
#include <string>
-
#include <list>
-
#include <vector>
-
#include <map>
-
#include <stack>
-
#include <opencv2/core/core.hpp>
-
#include <opencv2/highgui/highgui.hpp>
-
#include <opencv2/imgproc/imgproc.hpp>
-
-
-
using
namespace std;
-
using
namespace cv;
-
-
-
//------------------------------【两步法新改进版】----------------------------------------------
-
// 对二值图像进行连通区域标记,从1开始标号
-
void Two_PassNew(const Mat &bwImg, Mat &labImg)
-
{
-
assert(bwImg.
type() == CV_8UC1);
-
labImg.
create(bwImg.
size(), CV_32SC1);
//bwImg.convertTo( labImg, CV_32SC1 );
-
labImg =
Scalar(
0);
-
labImg.
setTo(
Scalar(
1), bwImg);
-
assert(labImg.
isContinuous());
-
const
int Rows = bwImg.rows -
1, Cols = bwImg.cols -
1;
-
int label =
1;
-
vector<
int> labelSet;
-
labelSet.
push_back(
0);
-
labelSet.
push_back(
1);
-
//the first pass
-
int *data_prev = (
int*)labImg.data;
//0-th row : int* data_prev = labImg.ptr<int>(i-1);
-
int *data_cur = (
int*)(labImg.data + labImg.step);
//1-st row : int* data_cur = labImg.ptr<int>(i);
-
for (
int i =
1; i < Rows; i++)
-
{
-
data_cur++;
-
data_prev++;
-
for (
int j =
1; j < Cols; j++, data_cur++, data_prev++)
-
{
-
if (*data_cur !=
1)
-
continue;
-
int left = *(data_cur -
1);
-
int up = *data_prev;
-
int neighborLabels[
2];
-
int cnt =
0;
-
if (left >
1)
-
neighborLabels[cnt++] = left;
-
if (up >
1)
-
neighborLabels[cnt++] = up;
-
if (!cnt)
-
{
-
labelSet.
push_back(++label);
-
labelSet[label] = label;
-
*data_cur = label;
-
continue;
-
}
-
int smallestLabel = neighborLabels[
0];
-
if (cnt ==
2 && neighborLabels[
1] < smallestLabel)
-
smallestLabel = neighborLabels[
1];
-
*data_cur = smallestLabel;
-
// 保存最小等价表
-
for (
int k =
0; k < cnt; k++)
-
{
-
int tempLabel = neighborLabels[k];
-
int& oldSmallestLabel = labelSet[tempLabel];
//这里的&不是取地址符号,而是引用符号
-
if (oldSmallestLabel > smallestLabel)
-
{
-
labelSet[oldSmallestLabel] = smallestLabel;
-
oldSmallestLabel = smallestLabel;
-
}
-
else
if (oldSmallestLabel < smallestLabel)
-
labelSet[smallestLabel] = oldSmallestLabel;
-
}
-
}
-
data_cur++;
-
data_prev++;
-
}
-
//更新等价队列表,将最小标号给重复区域
-
for (
size_t i =
2; i < labelSet.
size(); i++)
-
{
-
int curLabel = labelSet[i];
-
int prelabel = labelSet[curLabel];
-
while (prelabel != curLabel)
-
{
-
curLabel = prelabel;
-
prelabel = labelSet[prelabel];
-
}
-
labelSet[i] = curLabel;
-
}
-
//second pass
-
data_cur = (
int*)labImg.data;
-
for (
int i =
0; i < Rows; i++)
-
{
-
for (
int j =
0; j < bwImg.cols -
1; j++, data_cur++)
-
*data_cur = labelSet[*data_cur];
-
data_cur++;
-
}
-
}
-
-
//-------------------------------【老版两步法】-------------------------------------------
-
void Two_PassOld(const cv::Mat& _binImg, cv::Mat& _lableImg)
-
{
-
//connected component analysis (4-component)
-
//use two-pass algorithm
-
//1. first pass: label each foreground pixel with a label
-
//2. second pass: visit each labeled pixel and merge neighbor label
-
//
-
//foreground pixel: _binImg(x,y) = 1
-
//background pixel: _binImg(x,y) = 0
-
-
if (_binImg.
empty() || _binImg.
type() != CV_8UC1)
-
{
-
return;
-
}
-
-
// 1. first pass
-
_lableImg.
release();
-
_binImg.
convertTo(_lableImg, CV_32SC1);
-
-
int label =
1;
// start by 2
-
std::vector<
int> labelSet;
-
labelSet.
push_back(
0);
//background: 0
-
labelSet.
push_back(
1);
//foreground: 1
-
-
int rows = _binImg.rows -
1;
-
int cols = _binImg.cols -
1;
-
for (
int i =
1; i < rows; i++)
-
{
-
int* data_preRow = _lableImg.
ptr<
int>(i -
1);
-
int* data_curRow = _lableImg.
ptr<
int>(i);
-
for (
int j =
1; j < cols; j++)
-
{
-
if (data_curRow[j] ==
1)
-
{
-
std::vector<
int> neighborLabels;
-
neighborLabels.
reserve(
2);
//reserve(n) 预分配n个元素的存储空间
-
int leftPixel = data_curRow[j -
1];
-
int upPixel = data_preRow[j];
-
if (leftPixel >
1)
-
{
-
neighborLabels.
push_back(leftPixel);
-
}
-
if (upPixel >
1)
-
{
-
neighborLabels.
push_back(upPixel);
-
}
-
if (neighborLabels.
empty())
-
{
-
labelSet.
push_back(++label);
//assign to a new label
-
data_curRow[j] = label;
-
labelSet[label] = label;
-
}
-
else
-
{
-
std::
sort(neighborLabels.
begin(), neighborLabels.
end());
-
int smallestLabel = neighborLabels[
0];
-
data_curRow[j] = smallestLabel;
-
-
//save equivalence
-
for (
size_t k =
1; k < neighborLabels.
size(); k++)
-
{
-
int tempLabel = neighborLabels[k];
-
int& oldSmallestLabel = labelSet[tempLabel];
-
if (oldSmallestLabel > smallestLabel)
-
{
-
labelSet[oldSmallestLabel] = smallestLabel;
-
oldSmallestLabel = smallestLabel;
-
}
-
else
if (oldSmallestLabel < smallestLabel)
-
{
-
labelSet[smallestLabel] = oldSmallestLabel;
-
}
-
}
-
}
-
-
}
-
}
-
}
-
//update equivalent labels
-
//assigned with the smallest label in each equivalent label set
-
for (
size_t i =
2; i < labelSet.
size(); i++)
-
{
-
int curLabel = labelSet[i];
-
int prelabel = labelSet[curLabel];
-
while (prelabel != curLabel)
-
{
-
curLabel = prelabel;
-
prelabel = labelSet[prelabel];
-
}
-
labelSet[i] = curLabel;
-
}
-
-
//2. second pass
-
for (
int i =
0; i < rows; i++)
-
{
-
int *data = _lableImg.
ptr<
int>(i);
-
for (
int j =
0; j < cols; j++)
-
{
-
int& pixelLabel = data[j];
-
pixelLabel = labelSet[pixelLabel];
-
}
-
}
-
}
-
-
-
//---------------------------------【种子填充法老版】-------------------------------
-
void SeedFillOld(const cv::Mat& binImg, cv::Mat& lableImg) //种子填充法
-
{
-
// 4邻接方法
-
-
-
if (binImg.
empty() ||
-
binImg.
type() != CV_8UC1)
-
{
-
return;
-
}
-
-
lableImg.
release();
-
binImg.
convertTo(lableImg, CV_32SC1);
-
-
int label =
1;
-
-
int rows = binImg.rows -
1;
-
int cols = binImg.cols -
1;
-
for (
int i =
1; i < rows -
1; i++)
-
{
-
int* data = lableImg.
ptr<
int>(i);
-
for (
int j =
1; j < cols -
1; j++)
-
{
-
if (data[j] ==
1)
-
{
-
std::stack<std::pair<
int,
int>> neighborPixels;
-
neighborPixels.
push(std::
pair<
int,
int>(i, j));
// 像素位置: <i,j>
-
++label;
// 没有重复的团,开始新的标签
-
while (!neighborPixels.
empty())
-
{
-
std::pair<
int,
int> curPixel = neighborPixels.
top();
//如果与上一行中一个团有重合区域,则将上一行的那个团的标号赋给它
-
int curX = curPixel.first;
-
int curY = curPixel.second;
-
lableImg.
at<
int>(curX, curY) = label;
-
-
neighborPixels.
pop();
-
-
if (lableImg.
at<
int>(curX, curY -
1) ==
1)
-
{
//左边
-
neighborPixels.
push(std::
pair<
int,
int>(curX, curY -
1));
-
}
-
if (lableImg.
at<
int>(curX, curY +
1) ==
1)
-
{
// 右边
-
neighborPixels.
push(std::
pair<
int,
int>(curX, curY +
1));
-
}
-
if (lableImg.
at<
int>(curX -
1, curY) ==
1)
-
{
// 上边
-
neighborPixels.
push(std::
pair<
int,
int>(curX -
1, curY));
-
}
-
if (lableImg.
at<
int>(curX +
1, curY) ==
1)
-
{
// 下边
-
neighborPixels.
push(std::
pair<
int,
int>(curX +
1, curY));
-
}
-
}
-
}
-
}
-
}
-
-
}
-
-
-
-
-
//-------------------------------------------【种子填充法新版】---------------------------
-
void SeedFillNew(const cv::Mat& _binImg, cv::Mat& _lableImg)
-
{
-
// connected component analysis(4-component)
-
// use seed filling algorithm
-
// 1. begin with a forgeground pixel and push its forground neighbors into a stack;
-
// 2. pop the pop pixel on the stack and label it with the same label until the stack is empty
-
//
-
// forground pixel: _binImg(x,y)=1
-
// background pixel: _binImg(x,y) = 0
-
-
-
if (_binImg.
empty() ||
-
_binImg.
type() != CV_8UC1)
-
{
-
return;
-
}
-
-
_lableImg.
release();
-
_binImg.
convertTo(_lableImg, CV_32SC1);
-
-
int label =
0;
//start by 1
-
-
int rows = _binImg.rows;
-
int cols = _binImg.cols;
-
-
Mat mask(rows, cols, CV_8UC1);
-
mask.
setTo(
0);
-
int *lableptr;
-
for (
int i =
0; i < rows; i++)
-
{
-
int* data = _lableImg.
ptr<
int>(i);
-
uchar *masKptr = mask.
ptr<uchar>(i);
-
for (
int j =
0; j < cols; j++)
-
{
-
if (data[j] ==
255 && mask.
at<uchar>(i, j) !=
1)
-
{
-
mask.
at<uchar>(i, j) =
1;
-
std::stack<std::pair<
int,
int>> neighborPixels;
-
neighborPixels.
push(std::
pair<
int,
int>(i, j));
// pixel position: <i,j>
-
++label;
//begin with a new label
-
while (!neighborPixels.
empty())
-
{
-
//get the top pixel on the stack and label it with the same label
-
std::pair<
int,
int> curPixel = neighborPixels.
top();
-
int curY = curPixel.first;
-
int curX = curPixel.second;
-
_lableImg.
at<
int>(curY, curX) = label;
-
-
//pop the top pixel
-
neighborPixels.
pop();
-
-
//push the 4-neighbors(foreground pixels)
-
-
if (curX -
1 >=
0)
-
{
-
if (_lableImg.
at<
int>(curY, curX -
1) ==
255 && mask.
at<uchar>(curY, curX -
1) !=
1)
//leftpixel
-
{
-
neighborPixels.
push(std::
pair<
int,
int>(curY, curX -
1));
-
mask.
at<uchar>(curY, curX -
1) =
1;
-
}
-
}
-
if (curX +
1 <= cols -
1)
-
{
-
if (_lableImg.
at<
int>(curY, curX +
1) ==
255 && mask.
at<uchar>(curY, curX +
1) !=
1)
-
// right pixel
-
{
-
neighborPixels.
push(std::
pair<
int,
int>(curY, curX +
1));
-
mask.
at<uchar>(curY, curX +
1) =
1;
-
}
-
}
-
if (curY -
1 >=
0)
-
{
-
if (_lableImg.
at<
int>(curY -
1, curX) ==
255 && mask.
at<uchar>(curY -
1, curX) !=
1)
-
// up pixel
-
{
-
neighborPixels.
push(std::
pair<
int,
int>(curY -
1, curX));
-
mask.
at<uchar>(curY -
1, curX) =
1;
-
}
-
}
-
if (curY +
1 <= rows -
1)
-
{
-
if (_lableImg.
at<
int>(curY +
1, curX) ==
255 && mask.
at<uchar>(curY +
1, curX) !=
1)
-
//down pixel
-
{
-
neighborPixels.
push(std::
pair<
int,
int>(curY +
1, curX));
-
mask.
at<uchar>(curY +
1, curX) =
1;
-
}
-
}
-
}
-
}
-
}
-
}
-
}
-
-
-
//---------------------------------【颜色标记程序】-----------------------------------
-
//彩色显示
-
cv::Scalar GetRandomColor()
-
{
-
uchar r =
255 * (
rand() / (
1.0 + RAND_MAX));
-
uchar g =
255 * (
rand() / (
1.0 + RAND_MAX));
-
uchar b =
255 * (
rand() / (
1.0 + RAND_MAX));
-
return cv::
Scalar(b, g, r);
-
}
-
-
-
void LabelColor(const cv::Mat& labelImg, cv::Mat& colorLabelImg)
-
{
-
int num =
0;
-
if (labelImg.
empty() ||
-
labelImg.
type() != CV_32SC1)
-
{
-
return;
-
}
-
-
std::map<
int, cv::Scalar> colors;
-
-
int rows = labelImg.rows;
-
int cols = labelImg.cols;
-
-
colorLabelImg.
release();
-
colorLabelImg.
create(rows, cols, CV_8UC3);
-
colorLabelImg = cv::Scalar::
all(
0);
-
-
for (
int i =
0; i < rows; i++)
-
{
-
const
int* data_src = (
int*)labelImg.
ptr<
int>(i);
-
uchar* data_dst = colorLabelImg.
ptr<uchar>(i);
-
for (
int j =
0; j < cols; j++)
-
{
-
int pixelValue = data_src[j];
-
if (pixelValue >
1)
-
{
-
if (colors.
count(pixelValue) <=
0)
-
{
-
colors[pixelValue] =
GetRandomColor();
-
num++;
-
}
-
-
cv::Scalar color = colors[pixelValue];
-
*data_dst++ = color[
0];
-
*data_dst++ = color[
1];
-
*data_dst++ = color[
2];
-
}
-
else
-
{
-
data_dst++;
-
data_dst++;
-
data_dst++;
-
}
-
}
-
}
-
printf(
"color num : %d \n", num);
-
}
-
-
//------------------------------------------【测试主程序】-------------------------------------
-
int main()
-
{
-
-
cv::Mat binImage = cv::
imread(
"sda.jpg",
0);
-
//cv::threshold(binImage, binImage, 50, 1, CV_THRESH_BINARY);
-
cv::Mat labelImg;
-
double time;
-
time =
getTickCount();
-
-
SeedFillNew(binImage, labelImg);
-
time =
1000 * ((
double)
getTickCount() - time) /
getTickFrequency();
-
cout << std::fixed << time <<
"ms" << endl;
-
//彩色显示
-
/*
-
cv::Mat colorLabelImg;
-
LabelColor(labelImg, colorLabelImg);
-
cv::imshow("colorImg", colorLabelImg);
-
*/
-
//灰度显示
-
cv::Mat grayImg;
-
labelImg *=
10;
-
labelImg.
convertTo(grayImg, CV_8UC1);
-
cv::
imshow(
"labelImg", grayImg);
-
double minval, maxval;
-
minMaxLoc(labelImg, &minval, &maxval);
-
cout <<
"minval" << minval << endl;
-
cout <<
"maxval" << maxval << endl;
-
cv::
waitKey(
0);
-
return
0;
-
}
-
终于知道是啥原因了,我在进行Prewitt算子对边缘进行粗定位检测过后,没有进行去噪处理,一定要把图像转换为二值图像,就方便多了。并且还要记住,霍夫检测的直线像素是255白线才可以,经过长时间的试错终于解决了。输入原图像如下所示,我这里使用的去噪对比了四种,但是下面这种是最好的。Opencv 非局部降噪_51CTO博客_opencv降噪Opencv 非局部降噪,opencv自带的非局部降噪算法:CV_EXPORTS_WvoidfastNlMeansDenoising(InputArraysrc,OutputArraydst,floath=3,inttemplateWindowSize=7,intsearchWindowSize=21);h是过滤强度,templateWindowSize是分块大小,searchWindowSize是搜索区域大小。应用实例intmain(){MatI..https://blog.51cto.com/u_15458280/4843576
-
#include<opencv2/opencv.hpp>
-
#include<iostream>
-
using
namespace std;
-
using
namespace cv;
-
-
//数组从大到小排序
-
void reserve(int x[], int n) {
-
int i, j, temp;
-
for (i =
0; i < n -
1; i++) {
//一共n个元素,则需要比较n-1次
-
for (j =
0; j < n -
1 - i; j++) {
//每一个元素需要比较的次数
-
if (x[i] < x[i + j +
1]) {
-
temp = x[i];
-
x[i] = x[i + j +
1];
-
x[i + j +
1] = temp;
-
}
-
}
-
}
-
}
-
-
void add_salt_pepper_noise(Mat &image) {
-
RNG rng(12345);
-
int h = image.rows;
-
int w = image.cols;
-
int nums =
10000;
-
for (
int i =
0; i < nums; i++) {
-
int x = rng.
uniform(
0, w);
-
int y = rng.
uniform(
0, h);
-
if (i %
2 ==
1) {
-
image.
at<Vec3b>(y, x) =
Vec3b(
255,
255,
255);
-
}
-
else {
-
image.
at<Vec3b>(y, x) =
Vec3b(
0,
0,
0);
-
}
-
}
-
imshow(
"salt pepper", image);
-
}
-
-
void gaussian_noise(Mat &image) {
-
Mat noise = Mat::
zeros(image.
size(), image.
type());
-
randn(noise, (
15,
15,
15), (
30,
30,
30));
-
Mat dst;
-
add(image, noise, dst);
-
imshow(
"gaussian noise", dst);
-
dst.
copyTo(image);
-
}
-
-
Mat convertTo3Channels(const Mat& binImg)
-
{
-
Mat three_channel = Mat::
zeros(binImg.rows, binImg.cols, CV_8UC3);
-
vector<Mat> channels;
-
for (
int i =
0; i <
3; i++)
-
{
-
channels.
push_back(binImg);
-
}
-
merge(channels, three_channel);
-
return three_channel;
-
}
-
-
int main(int argc, char*argv[])
-
{
-
//加载图像
-
Mat img, gray_image, dst;
-
img =
imread(
"垂直边缘.jpg");
-
Mat img1 =
imread(
"垂直边缘.jpg");
-
//判断图像是否导入成功
-
if (img.
empty())
-
{
-
cout <<
"加载失败" << endl;
-
return
-1;
-
}
-
//显示图像
-
namedWindow(
"original image", WINDOW_AUTOSIZE);
-
imshow(
"original image", img);
-
//转换灰度图像
-
cvtColor(img, gray_image, COLOR_BGR2GRAY);
-
//获取灰度图像宽度和高度
-
int width = gray_image.cols;
-
int height = gray_image.rows;
-
//遍历像素值(单通道)
-
for (
int row =
0; row < height; row++)
-
{
-
for (
int col =
0; col < width; col++)
-
{
-
int gray = gray_image.
at<uchar>(row, col);
-
gray_image.
at<uchar>(row, col) =
255 - gray;
//图像取反
-
};
-
};
-
namedWindow(
"inv_gray_image", WINDOW_AUTOSIZE);
-
imshow(
"inv_gray_image", gray_image);
-
-
-
Mat sh;
-
-
fastNlMeansDenoising(gray_image, sh,
21,
7,
21);
-
namedWindow(
"inv_gray_image1", WINDOW_AUTOSIZE);
-
imshow(
"inv_gray_image1", sh);
-
-
-
waitKey(
50);
-
-
-
//Mat s;
-
//获取灰度图像宽度和高度
-
width = sh.cols;
-
height = sh.rows;
-
//遍历像素值(单通道)
-
for (
int row =
0; row < height; row++)
-
{
-
for (
int col =
0; col < width; col++)
-
{
-
int gray = sh.
at<uchar>(row, col);
-
sh.
at<uchar>(row, col) =
255 - gray;
//图像取反
-
};
-
};
-
namedWindow(
"inv_gray_image2", WINDOW_AUTOSIZE);
-
imshow(
"inv_gray_image2", sh);
-
-
-
cv::
threshold(sh, sh,
50,
255, cv::THRESH_BINARY);
-
cv::
namedWindow(
"二值化", CV_WINDOW_NORMAL);
-
imshow(
"二值化", sh);
-
-
vector<Vec4i> lines;
-
HoughLinesP(sh, lines,
1, CV_PI /
180,
50,
100,
5);
-
int Length[
100] = {
0 };
//存放直线长度
-
for (
size_t i =
0; i < lines.
size(); i++)
-
{
-
Vec4i I = lines[i];
-
double x1 = I[
0];
-
double y1 = I[
1];
-
double x2 = I[
2];
-
double y2 = I[
3];
-
-
//筛选满足条件的点
-
if (
abs(x1 - x2) +
abs(y1 - y2) >
50)
-
{
-
Length[i] =
sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2));
-
//将满足条件的点画出
-
line(img,
Point2d(x1, y1),
Point2d(x2, y2),
Scalar(
0,
255,
255),
2);
-
-
cout <<
" " <<
"(" << x1 <<
"," << y1 <<
")" <<
" " <<
"(" << x2 <<
"," << y2 <<
")" << endl;
-
//line(canny, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
-
}
-
}
-
-
Mat imgShow;
-
imgShow = img;
-
resize(imgShow, imgShow,
Size(imgShow.cols /
4, imgShow.rows /
4));
-
imshow(
"imgShow", imgShow);
-
imwrite(
"shuchu.png", imgShow);
-
-
-
reserve(Length,
100);
-
for (
int i =
0; i <
100; i++) {
-
cout <<
"长度" << Length[i] << endl;
//输出排序后的数组元素
-
}
-
-
for (
size_t i =
0; i < lines.
size(); i++)
-
{
-
Vec4i I = lines[i];
-
double x1 = I[
0];
-
double y1 = I[
1];
-
double x2 = I[
2];
-
double y2 = I[
3];
-
cout <<
"sdjk" << endl;
-
cout <<
int(
sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) << endl;
-
//筛选满足条件的点
-
if ((
int(
sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) == Length[
0]) || (
int(
sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) == Length[
1]))
-
{
-
-
//将满足条件的点画出
-
line(img1,
Point2d(x1, y1),
Point2d(x2, y2),
Scalar(
0,
255,
255),
2);
-
-
cout <<
"djfkljsa " <<
"(" << x1 <<
"," << y1 <<
")" <<
" " <<
"(" << x2 <<
"," << y2 <<
")" << endl;
-
//line(canny, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
-
}
-
}
-
-
imgShow = img1;
-
resize(imgShow, imgShow,
Size(imgShow.cols /
4, imgShow.rows /
4));
-
imshow(
"imgShow2", imgShow);
-
imwrite(
"shuchu2.png", imgShow);
-
waitKey(
0);
-
return
0;
-
};
-
-
结果图如下所示:
终于弄出来了,去干饭。
转载:https://blog.csdn.net/m0_47489229/article/details/128948195