简体   繁体   中英

Using OpenCV to crop image from background (strip extraction)

I'm trying to extract the pad section from the following image with OpenCv. Starting with an image like this: 带背景条

I am trying to extract into an image like this:

在此处输入图片说明

to end up with an image something like this

在此处输入图片说明

I currently have the following

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('strip.png')

grayscale = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresholded = cv2.threshold(grayscale, 0, 255, cv2.THRESH_OTSU)
bbox = cv2.boundingRect(thresholded)
x, y, w, h = bbox
foreground = img[y:y+h, x:x+w]

cv2.imwrite("output.png", foreground)

Which outputs this:

在此处输入图片说明

If you look closely to the upper and the lower parts of the image, it seems more cluttered and the center part (which is your desired output), it looks soft and smooth.

Since the center part is homogeneous , a smoothing filter (like an erosion) won't effect that part so much, the upper part otherwise, would change noticeably more.

At the first step, I remove the black background with a simple thresholding. At further I did some smoothing effect on the image and compute the difference between the result and the original image, then thresholded the final result to remove the unwanted pixels.

Then I did some morphology to remove noisy residual of the process. At the end with the help of boundingRect command, I extracted the desired segment (the white contour):

background removed:

在此处输入图片说明

the difference image after bluring with erosion:

在此处输入图片说明

the difference image after opening process and a threshold:

在此处输入图片说明

And finally the bounding box of the white objects:

在此处输入图片说明

The code I wrote (C++ opencv):

Mat im = imread("E:/t.jpg", 0);
resize(im, im, Size() , 0.3, 0.3); // # resizing just for better visualization

Mat im1,im2, im3;

// Removing the black background:
threshold(im, im1, 50, 255, THRESH_BINARY);
vector<vector<Point>> contours_1;
findContours(im1, contours_1, RETR_CCOMP, CHAIN_APPROX_NONE);

Rect r = boundingRect(contours_1[0]);

im(r).copyTo(im);
im.copyTo(im3);

imshow("background removed", im); 

// detecting the cluttered parts and cut them:
erode(im, im2, Mat::ones(3, 3, CV_8U), Point(-1, -1), 3);

im2.convertTo(im2, CV_32F);
im3.convertTo(im3, CV_32F);
subtract(im2, im3, im1);

double min, max;
minMaxIdx(im1, &min, &max);
im1 = 255*(im1 - min) / (max - min);
im1.convertTo(im1, CV_8U);

imshow("the difference image", im1);

threshold(im1, im1, 250, 255, THRESH_BINARY);

erode(im1, im1, Mat::ones(3, 3, CV_8U), Point(-1, -1), 3);
dilate(im1, im1, Mat::ones(3, 3, CV_8U), Point(-1, -1), 7);

imshow("the difference image thresholded", im1);

vector<Point> idx, hull;
vector<vector<Point>> hullis;
findNonZero(im1, idx);
Rect rr = boundingRect(idx);

rectangle(im, rr, Scalar(255, 255, 255), 2);

imshow("Final segmentation", im);

waitKey(0);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM