I am new to computer version, I am trying to remove the background of the image given and make it white background. I have tried most of the codes shared here but non is working on my image.
code_1
code_2
code_3
code_4
input:
desired output:
Chanda Steven wrote:
I am new to computer version, I am trying to remove the background of
the image given and make it white background.
If that is all you want to do, then the following is a simple way to do that in Python/OpenCV/Numpy.
(But your desired result looks like an inverted result. So I am not sure what you want.)
If making the background white is all you want. Then convert the input to gray. Copy the input and use Numpy to change the background to white where gray is close to black.
Input:
import cv2
import numpy as np
# read image
img = cv2.imread("a_blob.jpg")
# convert img to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# change black to white
result = img.copy()
result[gray<=2] = (255,255,255)
# write results to disk
cv2.imwrite("a_blob_white.jpg", result)
# show results
cv2.imshow("RESULT", result)
cv2.waitKey(0)
Result:
If you remove background you not have your desider output.
The object in the image have a different processing, similar negative, but isn't negative.
If it was negative you got this result :
From output image it's very difficult understand what operations have been carried out.
Related
How can I grab an image from a region and properly use tesseract to translate to text? I got this currently:
img = ImageGrab.grab(bbox =(1341,182, 1778, 213))
tesstr = pytesseract.image_to_string(np.array(img), lang ='eng')
print (tesstr)
Issue is that it translates it incredibly wrong because the region it's getting the text from is in red with blue background, how can I improve its accuracy? Example of what it's trying to turn from image to text:
*Issue is that it translates it incredibly wrong because the region it's getting the text from is in red with blue background, how can I improve its accuracy? *
You should know the Improving the quality of the output. You need to try each of the suggested method listed. If you still can't achieve the desired result, you should look at the other methods:
Thresholding Operations using inRange
Changing Colorspaces
Image segmentation
To get the desired result, you need to get the binary mask of the image. Both simple threshold, and adaptive-threshold won't work for the input image.
To get the binary mask
Up-sample and convert input image to the HSV color-space
Set lower and higher color boundaries.
Result:
The OCR output for 0.37 version will be:
Day 20204, 16:03:12: Your ‘Metal Triangle Foundation’
was destroved!
Code:
import cv2
import numpy as np
import pytesseract
# Load the image
img = cv2.imread("b.png")
# Up-sample
img = cv2.resize(img, (0, 0), fx=2, fy=2)
# Convert to HSV color-space
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# Get the binary mask
msk = cv2.inRange(hsv, np.array([0, 0, 123]), np.array([179, 255, 255]))
# OCR
txt = pytesseract.image_to_string(msk)
print(txt)
# Display
cv2.imshow("msk", msk)
cv2.waitKey(0)
There is an option in the Tesseract API such that you are able to increase the DPI at which you examine the image to detect text. Higher the DPI, hihger the precision, till diminishing returns set in. More processing power is required. DPI should not exceed original image DPI.
Does anyone know how I can get these results better?
Total Kills: 15,230,550
Kill Details: (recorded after 2019/10,/Z3]
993,151 331,129
1,330,450 33,265,533
5,031,168
This is what it returns however it is meant to be the same as the image posted below, I am new to python so are there any parameters that I can add to make it read the image better?
img = cv2.imread("kills.jpeg")
text = pytesseract.image_to_string(img)
print(text)
This is my code to read the image, Is there anything I can add to make it read better? Also, the black boxes are to cover images that were interfering with the reading. I would like to also say that I have added the 2 black boxes to see if the images behind them were causing the issue, but I still get the same issue.
The missing knowledge is page-segmentation-mode (psm). You need to use them, when you can't get the desired result.
If we look at your image, the only artifacts are the black columns. Other than that, the image looks like a binary image. Suitable for tesseract to recognize the characters and the digits.
Lets try reading the image by setting the psm to 6.
6 Assume a single uniform block of text.
print(pytesseract.image_to_string(img, config="--psm 6")
The result will be:
Total Kills: 75,230,550
Kill Details: (recorded after 2019/10/23)
993,161 331,129
1,380,450 33,265,533
5,031,168
Update
The second way to solve the problem is getting binary mask and applying OCR to the mask features.
Binary-mask
Features of the binary-mask
As we can see the result is slightly different from the input image. Now when we apply OCR result will be:
Total Kills: 75,230,550
Kill Details: (recorded after 2019/10/23)
993,161 331,129
1,380,450 33,265,533
5,031,168
Code:
import cv2
import numpy as np
import pytesseract
# Load the image
img = cv2.imread("LuKz3.jpg")
# Convert to hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# Get the binary mask
msk = cv2.inRange(hsv, np.array([0, 0, 0]), np.array([179, 255, 154]))
# Extract
krn = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 3))
dlt = cv2.dilate(msk, krn, iterations=5)
res = 255 - cv2.bitwise_and(dlt, msk)
# OCR
txt = pytesseract.image_to_string(res, config="--psm 6")
print(txt)
# Display
cv2.imshow("res", res)
cv2.waitKey(0)
I wanted to work on a small project to challenge my computer vision and image processing skills. I came across a project where I want to remove the hidden marks from the image. Hidden here refers to the watermarks that are not easily visible in rgb space but when you convert into hsv or some other space the marks become visible.
Here's one example:
BGR SPACE:
HSV SPACE:
I've tried different ways but was able to implement a solution that would remove those watermarks from the image. I am posting this question here to get different ideas to tackle this problem.
What I have tried:
I have tried various approaches but none of them worked, sharing the code might not help. It is not necessary to provide code for it, a pseudo code, idea or any lead would be appreciated.
I noticed that the hidden marks are all the colors similar to RGB(90,94,105). And when I showed R, G, and B separately I noticed that the watermarks were only visible in B channel. I thought that if adjust/remove the marks in B channel and merge the image again, may be I could get better results.
Code:
b,g,r = cv2.split(img)
b = b//2;
r = cv2.merge((r,g,b))
cv2.imshow("image",r)
Problems: This doesn't does solve the problem, it did make the colors little dimmer but the image colors were also disturbed.
I tried playing around with B channel to see if could accomplish something.
I also noticed that if we convert the image to LUV space then the marks are visible in V space.
This might be a possible approach. The underlying idea is that there are edges visible in the HSV channel that are not present in the original image. Here are the H, S and V channels side-by-side:
So if we find the edges in the original image and the edges in the HSV image and difference them, the watermarking should show up. That can then be used as a mask to do in-painting in the original image with OpenCV inpaint.
I am just using ImageMagick here in Terminal, but it could all be done equally with OpenCV, PIL or scikit-image:
# Detect edges visible in original image and auto-level
convert watermarked.png -colorspace gray -auto-level -canny 0x1+1%+3% -auto-level RGB-edges.png
# Find visible edges in H, S and V colourspace, generate mean across all three and auto-level
convert watermarked.png -colorspace hsv -separate -canny 0x1+1%+3% -evaluate-sequence mean -auto-level HSV-edges.png
# Find changemask between the two sets of edges
convert RGB-edges.png HSV-edges.png -compose changemask -composite result.png
The idea is that the watermarking is now identified in black, so use the black areas (maybe morphologically closed) as a mask in OpenCV to inpaint - see link above.
I didn't find any answer that completely solved the question. I appreciate everyone's effort though (Thank you).
I did something on my own and would like to share. It results in little quality loss (a little bluish blurriness) but successfully removes the watermarks. The solution is very simple but took time to analyze the image.
I WOULD BE VERY GLAD IF SOMEONE CAN EXTEND THIS APPROACH AND COME UP WITH SOMETHING EVEN BETTER
I observed that the watermarks were only visible in B space (out of RGB) and there were no traces of watermarks in R and G space.
B space:
I also red somewhere that blue light contributes little to the overall image compared to R and G channel so here's what I decided to do.
Blur the B channel by a large enough amount to remove traces of those patterns. Here's how the B channel would appear afterwards:
Finally, merge the image with the new B channel, previous R and previous G channel. Here's how the RGB channel would appear afterwards:
The advantage of using approach is that the traces are gone.
The only disadvantage is that the bluish and purplish colors appear at the black edges and the image is a little bluish in general.
My Code:
import cv2
from matplotlib import pyplot as plt
import numpy as np
img = cv2.imread("img.png")
b, g, r = cv2.split(img) # split into B,G,R spaces
b = cv2.GaussianBlur(b, None, 8)
plt.imshow(cv2.merge((r,g,b)), cmap='gray')
Here is a slight variation and extension of your processing in Python/OpenCV.
The main difference is that I use the median rather than a blurring and that I try to extract the black lines and impose them on the median before recombining.
Input:
import cv2
import numpy as np
# read image
img = cv2.imread("cartoon_hidden_marks.png")
# separate channels
b,g,r = cv2.split(img)
# median filter blue
median = cv2.medianBlur(b, 21)
# threshold blue image to extract black lines
thresh = cv2.threshold(b, 20, 255, cv2.THRESH_BINARY)[1]
# apply thresh to median
b_new = cv2.bitwise_and(median, thresh)
# combine b_new, g, b
img_new = cv2.merge([b_new,g,r])
# write results to disk
cv2.imwrite("cartoon_hidden_marks_median.jpg", median)
cv2.imwrite("cartoon_hidden_marks_thresh.jpg", thresh)
cv2.imwrite("cartoon_hidden_marks_new_blue.jpg", b_new)
cv2.imwrite("cartoon_hidden_marks_result.png", img_new)
# display it
cv2.imshow("median", median)
cv2.imshow("thresh", thresh)
cv2.imshow("b_new", b_new)
cv2.imshow("img_new", img_new)
cv2.waitKey(0)
Blue channel median:
Blue channel threshold (for black lines):
New blue channel:
Result:
Many of the erroneous blue lines are now black, but not all. Increasing the threshold would have gotten more black lines, but then the hidden marks would have appeared again in part.
If you have managed to isolate the watermarks in any channel, you should be able to threshold it and create a binary mask. Then you could use inpainting to fill the gaps with something like:
clean_image = cv2.inpaint(marked_image, mask_of_marks, 3, cv2.INPAINT_TELEA)
Another trivial solution in Python/OpenCV is simply to replace the green channel for the blue channel, since most of the green channel is about the same intensity distribution as that of the blue channel.
Input:
import cv2
import numpy as np
# read image
img = cv2.imread("cartoon_hidden_marks.png")
# separate channels
b,g,r = cv2.split(img)
# combine replacing b with g
img_new = cv2.merge([g,g,r])
# write results to disk
cv2.imwrite("cartoon_hidden_marks_result2.png", img_new)
# display it
cv2.imshow("result", img_new)
cv2.waitKey(0)
Result:
The issue is that the coat and the green tree are slightly different color and texture.
One might try modifying a copy of the green channel image to have the mean and standard-deviation as the blue channel to fix the coat issue. For the green tree, it is outside the region of the watermark, so one could mask that using inRange for the green tree color and then replace the blue channel image's tree in the copy of the green channel. Then recombine the modified green channel in place of the blue channel.
I need help thresholding a picture. I need identify different types of gummies but i cannot get past the thresholding part of my project.
I have various pictures but this is one of them:
I have done this using mean_c threshold but i need better results to find the countours after.
This is the original picture:
You may get better results by converting the image from RGB to HSV color space and threshold by hue (that's color value) and saturation (that's how much color is there compared to the gray value). Using saturation you might get the most of your gummies, except the transparent ones -- these are quite hard to get.
On the other hand, you may try to use edge detections, since your paper is flat and gummies really stand out. Here's the edge detection result I've got:
here's the code:
#!/usr/bin/env python
import cv2
img = cv2.imread( 'Downloads/gummies.jpg' )
img = cv2.pyrDown(cv2.pyrDown( img ))
laplacian = cv2.Laplacian(img, cv2.CV_8U)
cv2.normalize( laplacian, img, 0, 600, cv2.NORM_MINMAX)
cv2.imshow( 'frame', img )
cv2.waitKey(0)
cv2.destroyAllWindows()
I want to change the pixel value of a grayscale image using OpenCV.
Assume that I have a grayscale image and I want to convert all its pixel to 0 value one at a time. So that the resultant image is completely black. I tried this but there is no change in the image:
image = cv2.imread('test_image.png',0)
for i in range(image.shape[0]):
for j in range(image.shape[1]):
image[i, j] = 0
Result:
display the updated image
In most cases, you want to avoid using double for loops to modify pixel values since it is very slow. A better approach is to use Numpy for pixel modification since OpenCV uses Numpy arrays to display images. To achieve your desired result, you can use np.zeros to create a completely black image with the same shape as the original image.
import cv2
import numpy as np
image = cv2.imread("test_image.png", 0)
black = np.zeros(image.shape, np.uint8)
cv2.imshow('image', image)
cv2.imshow('black', black)
cv2.waitKey(0)
For example with a test image. Original (left), result (right)
I would suggest you to always try manipulating the copy of an image so that the image doesn't get affected in the wrong way. Coming to your question, you can do the following:
import cv2
image = cv2.imread('test_image.png',0)
#Creating a copy of the image to confirm right operation is performed on the image.
image_copy = image.copy()
image_copy[:,:] = [0] #Setting all values to 0.