0%

基于OpenCV的实用函数

  1. 1. 显示图像:showImage()
  2. 2. 三通道图像灰度化
  3. 3. 二维卷积
  4. 4. 从文件读取图片列表
  5. 5. 提取较粗的边缘,并对比

1. 显示图像:showImage()

1
2
3
4
5
6
7
8
9
10
/**
* 显示图像
*/
int showImage(Mat& src, int wk = 0, string winname = "Image", int flags = WINDOW_NORMAL, Size winsize = Size(500, 500))
{
namedWindow(winname, flags);
resizeWindow(winname, winsize.width, winsize.height);
imshow(winname, src);
return waitKey(wk);
}

2. 三通道图像灰度化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
* 图像灰度化
*/
int gray(Mat& src, Mat& dst)
{
// 获取图像宽高
int height, width;
height = src.rows;
width = src.cols;

// 初始化目标图像
dst.create(height, width, CV_8UC1);

// 灰度图
if (src.type() == CV_8UC1)
{
dst.data = src.data;
}
// 三通道图像
else if (src.type() == CV_8UC3)
{
uchar* s_ptr = src.data;
uchar* d_ptr = dst.data;

for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
d_ptr[i * width + j] = s_ptr[3 * (i * width + j) + 0] / 3
+ s_ptr[3 * (i * width + j) + 1] / 3 + s_ptr[3 * (i * width + j) + 2] / 3;
}
}
}
else
{
return -1;
}
return 0;
}

3. 二维卷积

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
* 卷积
*/
int conv(Mat& src, Mat& dst, Mat kernel = (Mat_<int>(3,3) << 0,-1,0,-1,5,-1,0,-1,0))
{
// 获取宽高
int w, h, ch;
w = src.cols;
h = src.rows;
ch = src.channels();

// 卷积核大小
int kw, kh;
kw = kernel.cols;
kh = kernel.rows;
if (kw != kh || kw % 2 == 0 || kh % 2 == 0) return -1;

// 卷积
dst = src.clone();
uchar* ptr = src.data;
uchar* d_ptr = dst.data;
int* k_ptr = (int*)kernel.data;
int s = kh / 2;
int light_sum;
for (int i=s; i<h-s; i++)
{
for (int j=s; j<w-s; j++)
{
// 遍历通道
for (int c=0; c < ch; c++)
{
light_sum = 0;
// 遍历卷积核
for (int m=0; m<kh; m++)
{
for (int n=0; n<kw; n++)
{

light_sum += int(ptr[ch * ((i-s+m)*w + (j-s+n)) + c]) * k_ptr[m*kw+n];
}
}
d_ptr[ch*(i*w+j) + c] = light_sum < 0 ? 0 : (light_sum > 255 ? 255 : light_sum);
}
}
}

return 0;
}

4. 从文件读取图片列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* 读取图片列表 */
void getImageList(vector<string>& imgList, string listFilePath = "./image-list.txt")
{
FILE* fp;
if (fopen_s(&fp, listFilePath.c_str(), "r") || !fp) return;
while (!feof(fp))
{
string filePath;
char ch = 0;
// 逐行读取
while (true) {
fscanf_s(fp, "%c", &ch, 1);
if (ch == '\n' || feof(fp)) break;
filePath.push_back(ch);
}
// 非零入列
if (filePath.size() != 0) imgList.push_back(filePath);
}
fclose(fp);
}

5. 提取较粗的边缘,并对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*提取较粗边缘*/
void getCoarseEdge(Mat &src, Mat &dst)
{
if (!src.data)
{
cout << QString("输入图像为空").toLocal8Bit().toStdString() << endl;
return;
}

// 灰度化
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);

gray.convertTo(gray, CV_32FC1);

// Sobel 八个方向
Mat leftTopSobelKernel = (Mat_<float>(3, 3) <<
2, 1, 0,
1, 0, -1,
0, -1, -2);
Mat topSobelKernel = (Mat_<float>(3, 3) <<
1, 2, 1,
0, 0, 0,
-1, -2, -1);
Mat rightTopSobelKernel = (Mat_<float>(3, 3) <<
0, 1, 2,
-1, 0, 1,
-2, -1, 0);
Mat rightSobelKernel = (Mat_<float>(3, 3) <<
-1, 0, 1,
-2, 0, 2,
-1, 0, 1);
Mat rightBottomSobelKernel = -leftTopSobelKernel;
Mat bottomSobelKernel = -topSobelKernel;
Mat leftBottomSobelKernel = -rightTopSobelKernel;
Mat leftSobelKernel = -rightSobelKernel;
Mat g1, g2, g3, g4, g5, g6, g7, g8;
filter2D(gray, g1, CV_32F, leftTopSobelKernel);
filter2D(gray, g2, CV_32F, topSobelKernel);
filter2D(gray, g3, CV_32F, rightTopSobelKernel);
filter2D(gray, g4, CV_32F, rightSobelKernel);
filter2D(gray, g5, CV_32F, rightBottomSobelKernel);
filter2D(gray, g6, CV_32F, bottomSobelKernel);
filter2D(gray, g7, CV_32F, leftBottomSobelKernel);
filter2D(gray, g8, CV_32F, leftSobelKernel);

gray.release();

Mat result = ((abs(g1) + abs(g2) + abs(g3) + abs(g4) + abs(g5) + abs(g6) + abs(g7) + abs(g8)) / 8);
g1.release();
g2.release();
g3.release();
g4.release();
g5.release();
g6.release();
g7.release();
g8.release();

double maxLight;
minMaxIdx(result, NULL, &maxLight);
result.convertTo(dst, CV_8UC1, 255.0 / maxLight);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* 边缘对比 */
void compareEdge(Mat& img1, Mat& img2)
{
// 提取边缘
Mat edge1, edge2;
getCoarseEdge(img1, edge1);
getCoarseEdge(img2, edge2);

cvtColor(edge1, edge1, COLOR_GRAY2BGR);

for (int i=0; i<edge1.rows; i++)
{
for (int j=0; j<edge1.cols; j++)
{
edge1.at<Vec3b>(i, j)[2] = edge2.at<uchar>(i, j);
}
}

showImage(edge1, 0, "Compare");
}