I would like to darken one image based on the mask of an edge-detected second image.
Image 1: Original (greyscale) image
Image 2: Edge detected (to be used as mask)
Image 3: Failed example showing cv2.subtract processing
In my failed example (Image 3), I subtracted the white pixels (255) from the original image but what I want to do is DARKEN the original image based on a mask of the edge detected image.
In this article: How to fast change image brightness with python + OpenCV?, Bill Gates describes how he converts the image to HSV, splits out then modifies Value, and then finally merges back. This seems like a reasonable approach but I only want to modify the Value where the mask is white i.e. the edge exists.
Ultimately, I am trying to enhance the edge of a low resolution thermal video stream in a similar way to the FLIR One VividIR technology.
I believe that I've made it really far as a complete novice to image processing, OpenCV and Python but after days now of trying just about every function OpenCV offers, I've got myself stuck.
## get the edge coordinates
pos = np.where(edge >0)
## divide
img[pos] //=2
Related
First image is the Original image. Second image is the Processed image. The image consists of a test tube containing some amount of precipitate at the bottom. I am trying to crop out only the Precipitate area of the image.
For achieving this, I have tried processing the original image so that the Upper edge of precipitate is detected. I am able to detect the upper edge of precipitate as you can see in the Processed image.
My question is, how do I crop the image from that upper edge to the bottom of test tube using OpenCV (Python) or some other library perhaps ? I am open to ideas and codes that can help. Thanks!
Original image
Processed image
The surface of the precipitate is bright.
This is what you can get by getting the saturation component, applying Gaussian filtering horizontally and binarizing.
Horizontal delimitation of the ROI should not be difficult.
I was trying a pencil sketch effect in OpenCV. The post I was reading applied linear dodge on the image, with blurred (negative image) as mask to obtain the effect.
inv=255-img
blur=cv2.GaussianBlur(inv,(21,21),0,0)
res=cv2.divide(img,255-blur,scale=256)
but I found out that the effect can be achieved without inverting the image(results at the bottom, left -with inverse and right without inverse)
I did this.
blur2=cv2.GaussianBlur(img,(21,21),0,0)
res = cv2.divide(img,blur2,scale=256)
I also read in some StackOverflow answer, and they also suggested the first approach.
I wanted to know why it is required to apply blur to the negative if we are converting back to the original?
Thank you for taking out your time to answer the question.
Instructions to convert image to sketch in the book "opencv with python blueprints".
Convert the colour image to grayscale.
Invert the grayscale image to get a negative.
Apply a Gaussian blur to the negative from step 2.
Blend the grayscale image from step 1 with the blurred negative from step 3 using a colour dodge.
Reference
I'm trying to extract some contents from a cropped image. I tried pytesseract and opencv template matching but the results are very poor. OpenCV template matching sometimes fails due to poor quality of the icons and tesseract gives me a line of text with false characters.
I'm trying to grab the values like this:
0:26 83 1 1
Any thoughts or techniques?
A technique you could use would be to blur your image. From what it looks like, the image is kind of low res and blurry already, so you wouldn't need to blur the image super hard. Whenever I need to use a blur function in Opencv, I normally choose the gaussian blur, as its technique of blurring each pixel as well as each surrounding pixel is great. Once the image is blurred, I would threshold, or adaptive threshold the image. Once you have gotten this far, the image that should be shown should be mostly hard lines with little bits of short lines mixed between. Afterwards, dilate the threshold image just enough to have the bits where there are a lot of hard edges connect. Once a dilate has been performed, find the contours of that image, and sort based on their height with the image. Since I assume the position of those numbers wont change, you will only have to sort your contours based on the height of the image. Afterwards, once you have sorted your contours, just create bounding boxes over them, and read the text from there.
However, if you want to do this the quick and dirty way, you can always just manually create your own ROI's around each area you want to read and do it that way.
First Method
Gaussian blur the image
Threshold the image
Dilate the image
Find Contours
Sort Contours based on height
Create bounding boxes around relevent contours
Second Method
Manually create ROI's around the area you want to read text from
Input image
I need to group the region in green and get its coordinates, like this output image. How to do this in python?
Please see the attached images for better clarity
At first, split the green channel of the image, put a threshold on that and have a binary image. This binary image contains the objects of the green area. Start dilating the image with the suitable kernel, this would make adjacent objects stick to each other and become to one big object. Then use findcontour to take the sizes of all objects, then hold the biggest object and remove the others, this image would be your mask. Now you can reconstruct the original image (green channel only) with this mask and fit a box to the remained objects.
You can easily find the code each part.
I am trying to validate black and white images (more of a clipart images - not photos) for an engraving machine.
One of the major things I need to take into consideration is the size of areas (or width of lines) since the machine can't handle lines that are too thin - so I need to find areas that are thinner than a given threshold.
Take this image for example:
The strings of the harp might be too thin to engrave.
I am reading about Matlab and OpenCV but image processing is an area I am learning about for the first time.
I am a Java / C# developer so implementation done with one of those languages will be best for me but any direction will be greatly appreciated.
A solution using matlab utilizing image morphological operations:
Define the minimal thickness of allowed area, for example, minThick=4
BW = imread('http://i.stack.imgur.com/oXKep.jpg');
BW = BW(:,:,1) < 128; %// convert image to binary mask
se = strel('disk', minTick/2, 0); %// define a disk element
eBW = imerode( BW, se ); %// "chop" half thickness from mask
deBW = imdilate( eBW, se ); %// dilate the eroded mask
Eroding and dilating should leave regions that are thicker than minThick unchanged, but it will remove the thin areas
invalidArea = BW & ~deBW; %// pixels that are in BW but not in deBW
Resulting with:
You can read more about imdilate and imerode in the linked documentation.
This is primarily for self-containment, but this is the equivalent code to what #Shai has performed in Python. I used the numpy and OpenCV packages from Python. The equivalent code to doing it in Python would simply be this:
import numpy as np # Import numpy package
import cv2 # Import OpenCV package
orig = cv2.imread('oXKep.jpg') # Read in image from disk
BW = orig[:,:,2] < 128 # Threshold below 128 to invert image
minThick = 5 # Define minimum thickness
se = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (minThick,minThick)) # define a disk element
finalBW = 255*cv2.morphologyEx(BW.astype('uint8'), cv2.MORPH_OPEN, se) # "chop" half thickness from mask and dilate the eroded mask
# Find invalid area
invalidArea = 255*np.logical_and(BW, np.logical_not(finalBW)).astype('uint8')
# Show original image
cv2.imshow('Original', orig)
# Show opened result
cv2.imshow('Final', finalBW)
# Show invalid lines
cv2.imshow('Invalid Area', invalidArea)
# Wait for user input then close windows
cv2.waitKey(0)
cv2.destroyAllWindows()
A few intricacies that I need to point out:
OpenCV's imread function reads in colour channels in reverse order with respect to MATLAB. Specifically, the channels are read in with a blue-green-red order. This means that the first channel is blue, the second channel green and third channel red. In MATLAB, these are read in proper RGB order. Because this is a grayscale image, the RGB components are the same so it really doesn't matter which channel you use. However, in order to be consistent with Shai's method, the red channel is being accessed and so we need to access the last channel of the image through OpenCV.
The disk structuring element in MATLAB with a structure number of 0 is essentially a diamond shape. However, because OpenCV does not have this structuring element built-in, and I wanted to produce the minimum amount of code possible to get something going, the closest thing I could use was the elliptical shaped structuring element.
In order for the structuring element to be symmetric, you need to make sure that the size is odd, so I changed the size from 4 to 5 from Shai's example.
In order to show an image using OpenCV Python, the image must be at least an unsigned 8-bit integer type. Binary images for display using OpenCV are not supported, and so I artificially made the binary images uint8 and multiplied the values by 255 before displaying them.
You can combine the erosion and dilation operations into one operation using morphological opening. Opening seeks to remove thin lines or disconnect objects that are thinly connected but maintain the shape of the original more larger objects. This is the the point of eroding first so that you can remove these lines but you will shrink the objects a bit in terms of the area, then dilating after so that you can restore the shapes back to their original size (mostly). I exploited that by performing a morphological opening via cv2.morphologyEx.
This is what I get: