python opencv 腐蚀_Opencv 腐蚀

将imori.jpg大津二值化之后,进行两次形态学腐蚀处理。

形态学处理中腐蚀操作如下:对于待操作的像素I(x,y)=255,I(x, y-1),I(x-1, y),I(x+1, y),I(x, y+1)中不论哪一个不为255,令I(x,y)=0。

morphology_dilate.png

在实际进行形态学处理的时候,待操作的像素4-近邻与矩阵\left[\begin{matrix}0&1&0\\1&0&1\\0&1&0\end{matrix}\right]相乘,结果小于255\times 4的话,将中心像素设为0。

python实现:

import cv2

import numpy as np

import matplotlib.pyplot as plt

# Gray scale

def BGR2GRAY(img):

b = img[:, :, 0].copy()

g = img[:, :, 1].copy()

r = img[:, :, 2].copy()

# Gray scale

out = 0.2126 * r + 0.7152 * g + 0.0722 * b

out = out.astype(np.uint8)

return out

# Otsu Binalization

def otsu_binarization(img, th=128):

H, W = img.shape

out = img.copy()

max_sigma = 0

max_t = 0

# determine threshold

for _t in range(1, 255):

v0 = out[np.where(out < _t)]

m0 = np.mean(v0) if len(v0) > 0 else 0.

w0 = len(v0) / (H * W)

v1 = out[np.where(out >= _t)]

m1 = np.mean(v1) if len(v1) > 0 else 0.

w1 = len(v1) / (H * W)

sigma = w0 * w1 * ((m0 - m1) ** 2)

if sigma > max_sigma:

max_sigma = sigma

max_t = _t

# Binarization

print("threshold >>", max_t)

th = max_t

out[out < th] = 0

out[out >= th] = 255

return out

# Morphology Dilate

def Morphology_Dilate(img, Erode_time=1):

H, W = img.shape

out = img.copy()

# kernel

MF = np.array(((0, 1, 0),

(1, 0, 1),

(0, 1, 0)), dtype=np.int)

# each erode

for i in range(Erode_time):

tmp = np.pad(out, (1, 1), 'edge')

# erode

for y in range(1, H+1):

for x in range(1, W+1):

if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) < 255*4:

out[y-1, x-1] = 0

return out

# Read image

img = cv2.imread("imori.jpg").astype(np.float32)

# Grayscale

gray = BGR2GRAY(img)

# Otsu's binarization

otsu = otsu_binarization(gray)

# Morphology - dilate

out = Morphology_Dilate(otsu, Erode_time=2)

# Save result

cv2.imwrite("out.jpg", out)

cv2.imshow("result", out)

cv2.waitKey(0)

cv2.destroyAllWindows()

c++实现:

#include

#include

#include

#include

// BGR -> Gray

cv::Mat BGR2GRAY(cv::Mat img){

// get height and width

int width = img.cols;

int height = img.rows;

// prepare output

cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);

// each y, x

for (int y = 0; y < height; y++){

for (int x = 0; x < width; x++){

// BGR -> Gray

out.at(y, x) = 0.2126 * (float)img.at(y, x)[2] \

+ 0.7152 * (float)img.at(y, x)[1] \

+ 0.0722 * (float)img.at(y, x)[0];

}

}

return out;

}

// Gray -> Binary

cv::Mat Binarize_Otsu(cv::Mat gray){

int width = gray.cols;

int height = gray.rows;

// determine threshold

double w0 = 0, w1 = 0;

double m0 = 0, m1 = 0;

double max_sb = 0, sb = 0;

int th = 0;

int val;

// Get threshold

for (int t = 0; t < 255; t++){

w0 = 0;

w1 = 0;

m0 = 0;

m1 = 0;

for (int y = 0; y < height; y++){

for (int x = 0; x < width; x++){

val = (int)(gray.at(y, x));

if (val < t){

w0++;

m0 += val;

} else {

w1++;

m1 += val;

}

}

}

m0 /= w0;

m1 /= w1;

w0 /= (height * width);

w1 /= (height * width);

sb = w0 * w1 * pow((m0 - m1), 2);

if(sb > max_sb){

max_sb = sb;

th = t;

}

}

std::cout << "threshold:" << th << std::endl;

// prepare output

cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);

// each y, x

for (int y = 0; y < height; y++){

for (int x = 0; x < width; x++){

// Binarize

if (gray.at(y, x) > th){

out.at(y, x) = 255;

} else {

out.at(y, x) = 0;

}

}

}

return out;

}

// Morphology Dilate

cv::Mat Morphology_Dilate(cv::Mat img, int Dilate_time){

int height = img.cols;

int width = img.rows;

// output image

cv::Mat tmp_img;

cv::Mat out = img.clone();

// for erode time

for (int i = 0; i < Dilate_time; i++){

tmp_img = out.clone();

// each pixel

for (int y = 0; y < height; y++){

for (int x = 0; x < width; x++){

// check left pixel

if ((x > 0) && (tmp_img.at(y, x - 1) == 0)){

out.at(y, x) = 0;

continue;

}

// check up pixel

if ((y > 0) && (tmp_img.at(y - 1, x) == 0)){

out.at(y, x) = 0;

continue;

}

// check right pixel

if ((x < width - 1) && (tmp_img.at(y, x + 1) == 0)){

out.at(y, x) = 0;

continue;

}

// check left pixel

if ((y < height - 1) && (tmp_img.at(y + 1, x) == 0)){

out.at(y, x) = 0;

continue;

}

}

}

}

return out;

}

int main(int argc, const char* argv[]){

// read image

cv::Mat img = cv::imread("imori.jpg", cv::IMREAD_COLOR);

// BGR -> Gray

cv::Mat gray = BGR2GRAY(img);

// Gray -> Binary

cv::Mat bin = Binarize_Otsu(gray);

// Morphology Dilate

cv::Mat out = Morphology_Dilate(bin, 2);

//cv::imwrite("out.jpg", out);

cv::imshow("sample", out);

cv::waitKey(0);

cv::destroyAllWindows();

return 0;

}

输入:

imori.jpg

大津二值化:

answer_4.jpg

输出:

answer_48.jpg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值