(1)先使用 Otsu's 二值化对图像进行二值化 (2)使用开运算去除图像中的细小白色噪点 (3)通过距离变换来确定前景图像 (4)可以看到硬币的中心像素值最大(中心离背景像素最远)。对其进行二值处理就得到了分离的前景图。 (5)通过膨胀运算,使得一部分背景成为了物体到的边界,得到的图像中的黑色区域肯定是真实背景。 (6)使用膨胀图减去前景图,得到不确定区域,这部分区域不确定是硬币还是背景,这些区域通常在前景和背景接触的区域(或者两个不同硬币接触的区域),称之为边界。通过分水岭算法应该能找到确定的边界。 (7)现在可以确定哪些是硬币区域,哪些是背景区域。然后需要创建标记(marker,它是一个与原始图像大小相同的矩阵,int32数据类型),表示其中的每个区域。分水岭算法将标记的0的区域视为不确定区域,将标记为1的区域视为背景区域,将标记大于1的正整数表示我们想得到的前景。 (8)可以使用 connectedComponents() 来实现这个功能,它是用0标记图像的背景,用大于0的整数标记其他对象。但是OpenCV的分水岭分割函数,会用0表示不确定区域,所以需要对标记统一加一,然后将上一步计算的不确定区域部分标记为0. (9)现在可以调用watershed函数分割图像,如下: watershed(src, markers); (10)maker中标记为-1的地方就是分界线,makers中的最大值减1就是统计的个数。
时间: 2024-02-22 18:01:28 浏览: 19
这是一个关于图像处理的流程,你需要使用 Otsu's 二值化、开运算、距离变换、膨胀运算、分水岭算法等技术来处理图像,最后可以确定哪些是硬币区域,哪些是背景区域,然后使用 connectedComponents() 函数来实现这个功能,最后调用 watershed() 函数分割图像。这个流程可以用来统计硬币的个数。
相关问题
用python写图像二值化,形态学处理,轮廓提取,抠图,抠出来的图为主体对其更换背景在进行高斯模糊的代码
以下是使用Python进行图像二值化,形态学处理,轮廓提取,抠图,抠出来的图为主体对其更换背景在进行高斯模糊的示例代码:
```
import cv2
import numpy as np
# 读取图像
img = cv2.imread('input.jpg')
# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化处理
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# 形态学开运算,去除噪点
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
# 轮廓提取
contours, hierarchy = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 获取包含连通区域的矩形
rect = cv2.boundingRect(contours[0])
# 抠图
foreground = img[rect[1]:rect[1]+rect[3], rect[0]:rect[0]+rect[2]]
# 更换背景
background = cv2.imread('background.jpg')
background = cv2.resize(background, (img.shape[1], img.shape[0]))
background[rect[1]:rect[1]+rect[3], rect[0]:rect[0]+rect[2]] = foreground
# 高斯模糊
blurred = cv2.GaussianBlur(background, (51,51), 0)
# 显示结果
cv2.imshow('result', blurred)
cv2.waitKey(0)
```
其中,`input.jpg`是待处理的图片,`background.jpg`是要替换的背景图片,需要保证两者大小相同。运行代码后会显示处理后的结果图片。
Opencv c++代码实现分水岭分割算法,并将其用于下面图像分割,其算法:(1)先使用 Otsu's 二值化对图像进行二值化 (2)使用开运算去除图像中的细小白色噪点 (3)通过距离变换来确定前景图像 (4)可以看到硬币的中心像素值最大(中心离背景像素最远)。对其进行二值处理就得到了分离的前景图。 (5)通过膨胀运算,使得一部分背景成为了物体到的边界,得到的图像中的黑色区域肯定是真实背景。 (6)使用膨胀图减去前景图,得到不确定区域,这部分区域不确定是硬币还是背景,这些区域通常在前景和背景接触的区域(或者两个不同硬币接触的区域),称之为边界。通过分水岭算法应该能找到确定的边界。 (7)现在可以确定哪些是硬币区域,哪些是背景区域。然后需要创建标记(marker,它是一个与原始图像大小相同的矩阵,int32数据类型),表示其中的每个区域。分水岭算法将标记的0的区域视为不确定区域,将标记为1的区域视为背景区域,将标记大于1的正整数表示我们想得到的前景。 (8)可以使用 connectedComponents() 来实现这个功能,它是用0标记图像的背景,用大于0的整数标记其他对象。但是OpenCV的分水岭分割函数,会用0表示不确定区域,所以需要对标记统一加一,然后将上一步计算的不确定区域部分标记为0. (9)现在可以调用watershed函数分割图像,如下: watershed(src, markers); (10)maker中标记为-1的地方就是分界线,makers中的最大值减1就是统计的个数。
以下是 Opencv c++ 代码实现分水岭分割算法,实现对图像的分割:
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat img = imread("coins.jpg", IMREAD_GRAYSCALE);
if (img.empty())
{
cout << "Could not read the image!" << endl;
return -1;
}
// Otsu's 二值化
Mat binary;
threshold(img, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
// 开运算去除细小白色噪点
Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));
morphologyEx(binary, binary, MORPH_OPEN, kernel);
// 距离变换
Mat dist;
distanceTransform(binary, dist, DIST_L2, 3);
// 取硬币中心像素值最大的区域作为前景图像
normalize(dist, dist, 0, 1, NORM_MINMAX);
threshold(dist, dist, 0.5, 1.0, THRESH_BINARY);
// 膨胀运算
Mat kernel2 = getStructuringElement(MORPH_ELLIPSE, Size(9, 9));
dilate(dist, dist, kernel2);
// 计算不确定区域
Mat sure_bg;
threshold(dist, sure_bg, 0.5, 1.0, THRESH_BINARY_INV);
Mat sure_fg;
threshold(dist, sure_fg, 0.5, 1.0, THRESH_BINARY);
// 不确定区域
Mat uncertain;
Mat uncertain_temp;
subtract(sure_bg, binary, uncertain_temp);
subtract(uncertain_temp, sure_fg, uncertain);
// 创建标记
Mat marker(binary.size(), CV_32S);
marker.setTo(0);
marker.setTo(1, sure_bg);
marker.setTo(2, uncertain);
marker.setTo(3, sure_fg);
// 分水岭算法
watershed(img, marker);
// 统计硬币个数
int coin_count = 0;
for (int i = 0; i < marker.rows; i++)
{
for (int j = 0; j < marker.cols; j++)
{
if (marker.at<int>(i, j) == -1)
{
coin_count++;
}
}
}
cout << "The number of coins is: " << coin_count << endl;
// 显示结果
Mat result;
convertScaleAbs(marker, result);
imshow("Result", result);
waitKey(0);
return 0;
}
```
这个程序实现了对硬币图像的分割,并统计了硬币的个数。