Reputation: 57
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:
Upvotes: 0
Views: 520
Reputation: 1855
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):
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);
Upvotes: 2