如何消除图像的模糊背景? [英] How to remove blurred background of images?

查看:51
本文介绍了如何消除图像的模糊背景?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从事叶病分类项目.我想使用高效的机器学习分割算法删除整个数据集的模糊背景.输出应为ROI的彩色版本.而且由于数据集的数量巨大,我想要一种训练时间更少的算法.所以,你能建议我坚持什么选择吗?

数据集示例如下.

我放大图像以连接附近的边缘(Canny提供了1像素宽的线条,这些线条很容易断开连接),然后使用findContours获取所有白线的轮廓.我对所有区域进行排序并选择最大的轮廓,然后使用该轮廓创建蒙版.

面具的参差不齐使我感到困扰,所以我先做一个打开操作(切除细锯齿),然后进行中值模糊处理(使边缘平滑).

然后所有要做的就是使用蒙版裁剪出图像并完成.(我必须将其更改为jpg,以使其限制为2mb,因此此处可能存在一些压缩伪像.)

这是代码(请注意,这是在OpenCV 3.4中,如果您使用的是其他主要版本,则必须修改find​​Contours行)

  import cv2将numpy导入为np#加载图片img = cv2.imread("leaf.jpg");#灰度灰色= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY);#坎尼罐头= cv2.Canny(灰色,0,100);#膨胀以封闭线中的孔内核= np.ones((3,3),np.uint8)mask = cv2.dilate(罐头,内核,迭代= 1);#找到轮廓#Opencv 3.4,如果使用其他主要版本(4.0或2.0),则删除第一个下划线_,轮廓,_ = cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE);#找到最大的轮廓maximum_cntr =无;maximum_area = 0;用于轮廓中的轮廓:面积= cv2.contourArea(轮廓);如果面积>最大区域:最大面积=面积;maximum_cntr =轮廓;#绘制轮廓crop_mask = np.zeros_like(掩码);cv2.drawContours(crop_mask,[biggest_cntr],-1,(255),-1);#打开+中值模糊以平滑锯齿crop_mask = cv2.erode(crop_mask,内核,迭代次数= 5);crop_mask = cv2.dilate(crop_mask,内核,迭代次数= 5);crop_mask = cv2.medianBlur(crop_mask,21);#裁剪图片作物= np.zeros_like(img);crop [crop_mask == 255] = img [crop_mask == 255];# 表演cv2.imshow("leaf",img);cv2.imshow(灰色",灰色);cv2.imshow(罐头",罐头);cv2.imshow("mask",crop_mask);cv2.imshow(裁剪",裁剪);cv2.waitKey(0); 

如果要将其概括为包括多个前景对象,则可以按大小过滤轮廓,并拒绝小于特定阈值的轮廓.

I am working on a project of leaf disease classification. I want to remove the blurred background of my entire dataset using an efficient machine learning segmentation algorithm. The output should be the colored version of ROI. And due to the huge volume of the dataset I want an algorithm with less training time. So, could you suggest me any option I may stick to?

The dataset sample is attached below.

leaf image with a disease symptom

解决方案

This particular problem isn't too difficult to solve. It's not as bad as it could be since there's only one foreground object which means we can solve it using simple methods. @Ceopee's instinct of edge detection is the correct one since it's the most obvious way that the foreground will differ from a blurry background.

I grayscaled the image and use a Canny edge detector. I didn't really tune it at all so we get a bunch of edges, but we only care about finding the edges of the leaves. Thankfully, we don't have to spend a bunch of time tuning it for each image since we only care about the biggest continuous edge.

I dilate the image to connect up nearby edges (canny gives 1 pixel wide lines which are easily disconnected) and then use findContours to get an outline of all of the white lines. I sort through and pick the biggest contour by area and use that one to create a mask.

The jaggedness of the mask bothers me so I do an opening operation (to cut off thin jaggies) followed by a median blur (to smooth out the edges).

Then all there is to do is use the mask to crop out the image and it's done. (I had to change it to a jpg to make the 2mb limit so there might be some compression artifacts on here).

Here's the code (Note this is in OpenCV 3.4, if you're using a different major version then you'll have to modify the findContours line)

import cv2
import numpy as np

# load image
img = cv2.imread("leaf.jpg");

# grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY);

# canny
canned = cv2.Canny(gray, 0, 100);

# dilate to close holes in lines
kernel = np.ones((3,3),np.uint8)
mask = cv2.dilate(canned, kernel, iterations = 1);

# find contours
# Opencv 3.4, if using a different major version (4.0 or 2.0), remove the first underscore
_, contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE);

# find the biggest contour
biggest_cntr = None;
biggest_area = 0;
for contour in contours:
    area = cv2.contourArea(contour);
    if area > biggest_area:
        biggest_area = area;
        biggest_cntr = contour;

# draw contours
crop_mask = np.zeros_like(mask);
cv2.drawContours(crop_mask, [biggest_cntr], -1, (255), -1);

# opening + median blur to smooth jaggies
crop_mask = cv2.erode(crop_mask, kernel, iterations = 5);
crop_mask = cv2.dilate(crop_mask, kernel, iterations = 5);
crop_mask = cv2.medianBlur(crop_mask, 21);

# crop image
crop = np.zeros_like(img);
crop[crop_mask == 255] = img[crop_mask == 255];

# show
cv2.imshow("leaf", img);
cv2.imshow("gray", gray);
cv2.imshow("canny", canned);
cv2.imshow("mask", crop_mask);
cv2.imshow("cropped", crop);
cv2.waitKey(0);

If you want to generalize this to include multiple foreground objects you could filter the contours by size and reject contours smaller than a certain threshold.

这篇关于如何消除图像的模糊背景?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆