Related
I have a image that is taken with uneven lighting.. there is a Light obove and one below the camera, so as a result, the image is properly lit in the center (top to bottom) but quite dark left and right.
Is there a way to apply a brightening filter with a gradient? so the more it nears the outer edge, the brighter it gets?
Solved with the answer from Mannari this way:
decompose3 (OriginalImage, ImageR, ImageG, ImageB)
trans_from_rgb(ImageR, ImageG, ImageB, ImageH, ImageL, ImageS, 'hls')
ImageWhite:=ImageL
gen_rectangle1(Rectangle,0,0,ImageHeight-1,ImageWidth-1)
* paint a white rectangle
paint_region(Rectangle,ImageWhite,ImageWhite,255.0,'fill')
tuple_real(BrightenWidth,BrightenWidth)
gen_image_gray_ramp (ImageGrayRampL, 0, -(255/BrightenWidth), 128, 1, BrightenWidth/2, ImageWidth, ImageHeight)
gen_image_gray_ramp (ImageGrayRampR, 0, (255/BrightenWidth), 128, 1, ImageWidth-(BrightenWidth/2), ImageWidth, ImageHeight)
add_image (ImageGrayRampL,ImageGrayRampR,ImageGrayRampRaw,1,0)
mult_image (ImageL, ImageGrayRampRaw, ImageComp, 0.003, 0)
add_image (ImageL, ImageComp, BrightenedImageL, 1, 0)
add_image (ImageS, ImageComp, BrightenedImageS, 1, 0)
trans_to_rgb(ImageH,BrightenedImageL,BrightenedImageS,ImageR,ImageG,ImageB,'hls')
compose3(ImageR,ImageG,ImageB,CompensatedImage)
Yes, of course.
You can find an example in the demo multi_image.dev.
Here the demo code:
* This example demonstrates how to multiply two images using
* the operator 'mult_image'.
*
*
dev_close_window ()
dev_update_off ()
*
* Read an input image and generate a second input image
* by creating a gray value ramp
read_image (Scene00, 'autobahn/scene_00')
gen_image_gray_ramp (ImageGrayRamp, 0.5, 0.5, 128, 256, 256, 512, 512)
*
* Display the input images for the multiplication
dev_open_window_fit_image (Scene00, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_display (Scene00)
disp_message (WindowHandle, 'Multiply the image with a gray value ramp', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
dev_display (ImageGrayRamp)
disp_message (WindowHandle, 'Created gray value ramp', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*
* Multiply the images with factor 0.005 for the gray value
* adaption and display the resulting image
mult_image (Scene00, ImageGrayRamp, ImageResult, 0.005, 0)
dev_display (ImageResult)
disp_message (WindowHandle, 'Resulting image of the product', 'window', 12, 12, 'black', 'true')
I think it's better if you grab a reference photo (for example with a white paper) instead of creating a gradient image.
1.Some Information: I would like to develop a kind of circle recognition with the help of openCV. I successfully set up a connection between Swift, objc-c++, but strangely I have some problems with the circle recognition algorithm: Not all of the circles in my image gets detected!
2.Have a look at my code:
+(UIImage *)ConvertImage:(UIImage *)image {
cv::Mat matImage;
UIImageToMat(image, matImage);
cv::Mat modImage;
cv::medianBlur(matImage, matImage, 5);
cv::cvtColor(matImage, modImage, CV_RGB2GRAY);
cv::GaussianBlur(modImage, modImage, cv::Size(9, 9), 2, 2);
vector<Vec3f> circles;
cv::HoughCircles(modImage, circles, CV_HOUGH_GRADIENT, 1, 1, 100, 50, 0, 0);
for (auto i = circles.begin(); i != circles.end(); ++i)
std::cout << *i << ' ';
for( size_t i = 0; i < circles.size(); i++ )
{
cv::Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
circle( matImage, center, 3, Scalar(0,255,0), -1, 8, 0 );
circle( matImage, center, radius, Scalar(0,0,255), 3, 8, 0 );
}
UIImage *binImg = MatToUIImage(matImage);
return binImg;
}
As you can see in the image [click] there appears this issue :
Only 3 of 7 circles gets detected!
So in the docs I found the parameters explanation for this line:
cv::HoughCircles(modImage, circles, CV_HOUGH_GRADIENT, 1, 1, 100, 50, 0, 0);
dp = 1: The inverse ratio of resolution.
min_dist = modImage.rows/8: Minimum distance between detected centers.
param_1 = 200: Upper threshold for the internal Canny edge detector.
param_2 = 100*: Threshold for center detection.
min_radius = 0: Minimum radio to be detected. If unknown, put zero as default.
max_radius = 0: Maximum radius to be detected. If unknown, put zero as default.
3.My question
How to get rid of the issue mentioned above?
Any help would be very appreciated :)
For issue number 2 : The outline should be colored, not white!
What color should it be? At any rate you draw that circle in your code with this line.
circle( matImage, center, radius, Scalar(0,0,255), 3, 8, 0 );
If you want to change the color you can change the values you have declared in Scalar(0,0,255).
If you dont want the circle there at all you can remove that line of code.
Your images seems to be noise free. If the image is to contain circle always, You can extract the contours and fit circles using Least Squares
You can get the circle fit equations here. It is a straightforward implementation. Create a structure for the circle parameters (center and radius), fit circle and store the parameters in the structure and use it to draw circle using OpenCV.
You can also generate points on the circle using "ellipse2poly" function.
Fingerprint sensor (Persona) is being used to get a fingerprint image. I am trying to enhance this image. I am using OpenCV for this purpose. Here is my original image:
I have applied otsu transform on it and got this image:
Now I have applied Gabor filter from OpenCV on orientations of 0, 45, 90, 135. I have got this result:
Here is my code in Python OpenCV for application of gabor filter:
import numpy as np
import cv2
from matplotlib import pyplot as plt
//cv2.getGaborKernel(ksize, sigma, theta, lambda, gamma, psi, ktype)
// ksize - size of gabor filter (n, n)
// sigma - standard deviation of the gaussian function
// theta - orientation of the normal to the parallel stripes
// lambda - wavelength of the sunusoidal factor
// gamma - spatial aspect ratio
// psi - phase offset
// ktype - type and range of values that each pixel in the gabor kernel
//canhold
g_kernel = cv2.getGaborKernel((25, 25), 6.0, np.pi/4, 8.0, 0.5, 0, ktype=cv2.CV_32F)
g_kernel1 = cv2.getGaborKernel((30, 30), 6.0, (3*np.pi)/4, 8.0, 0.5, 0, ktype=cv2.CV_32F)
g_kernel2 = cv2.getGaborKernel((30, 30),4 , 0, 8, 0.5, 0, ktype=cv2.CV_32F)
g_kernel3 = cv2.getGaborKernel((30, 30),4 , np.pi, 8, 0.5, 0, ktype=cv2.CV_32F)
print np.pi/4
img = cv2.imread('C:/Users/admin123/Desktop/p.png')
img1 = cv2.imread('C:/Users/admin123/Desktop/p.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
// Otsu thresholding
ret2,img1 = cv2.threshold(img1,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imshow('otsu', img1)
filtered_img = cv2.filter2D(img, cv2.CV_8UC3, g_kernel)
filtered_img1 = cv2.filter2D(img, cv2.CV_8UC3, g_kernel1)
filtered_img2 = cv2.filter2D(img, cv2.CV_8UC3, g_kernel2)
filtered_img3 = cv2.filter2D(img, cv2.CV_8UC3, g_kernel3)
cv2.imshow('0', filtered_img)
cv2.imshow('1', filtered_img1)
cv2.imshow('2', filtered_img2)
cv2.imshow('image', img)
cv2.addWeighted(filtered_img2,0.4,filtered_img1,0.8,0,img) #0 degree and 90
cv2.addWeighted(img,0.4,filtered_img,0.6,0,img) #0 degree and 90
cv2.addWeighted(img,0.4,filtered_img3,0.6,0,img)
cv2.addWeighted(img,0.4,img1,0.6,0.3,img)
cv2.imshow('per',img)
//threshold will convert it plain zero and white image
ret,thresh1 = cv2.threshold(img,150,255,cv2.THRESH_BINARY)#127 instead of 200
cv2.imshow('per1',thresh1)
h, w = g_kernel.shape[:2]
g_kernel = cv2.resize(g_kernel, (3*w, 3*h), interpolation=cv2.INTER_CUBIC)
g_kernel1 = cv2.resize(g_kernel1, (3*w, 3*h), interpolation=cv2.INTER_CUBIC)
cv2.imshow('gabor kernel (resized)', g_kernel)
cv2.imshow('gabor kernel1 (resized)', g_kernel1)
cv2.waitKey(0)
cv2.destroyAllWindows()
I want robust fingerprint recognition. For this I want image of this level to get accurate Minutiae points:
How can I get this much result from enhancement? What changes are required in code to get the enhanced result?
Well I dont have a python/opencv answer but I can point you the resource where you can fiddle around with a Matlab code. You can find the code here Simple Fingerprint Matcher
The code basically holds all the code for enhacement/minutiae extraction/matching. Though not very robust on matching but enhancements are pretty good.
I ran the code on the sample you uploaded, which came out as follows.
Note that the code uses two different approaches combined for fingerprint enhancement. One is based on Gabor filters and the other is called STFT (Short Time Fourier Transform), But it is likely that you will only need the Gabor filter part. Actually depends upon the image quality.
If you need the Gabor filter code in Matlab, you can find it herehttp://www.peterkovesi.com/matlabfns/#fingerprints
But I did modify the code to show up the images and process only a single finger.
The following is the main file calling in steps the extraction of enhanced fingerprint. The matlab function doing that is f_enhance.m
function [ binim, mask, cimg1, cimg2, oimg1, oimg2 ] = f_enhance( img )
enhimg = fft_enhance_cubs(img,6); % Enhance with Blocks 6x6
enhimg = fft_enhance_cubs(enhimg,12); % Enhance with Blocks 12x12
[enhimg,cimg2] = fft_enhance_cubs(enhimg,24); % Enhance with Blocks 24x24
blksze = 5; thresh = 0.085;
normim = ridgesegment(enhimg, blksze, thresh);
oimg1 = ridgeorient(normim, 1, 3, 3);
[enhimg,cimg1] = fft_enhance_cubs(img, -1);
[normim, mask] = ridgesegment(enhimg, blksze, thresh);
oimg2 = ridgeorient(normim, 1, 3, 3);
[freq, medfreq] = ridgefreq(normim, mask, oimg2, 32, 5, 5, 15);
binim = ridgefilter(normim, oimg2, medfreq.*mask, 0.5, 0.5, 1);
figure,imshow(binim,[]); % Normalize to grayscale
binim = ridgefilter(normim, oimg2, medfreq.*mask, 0.5, 0.5, 1) > 0;
figure;
figure,imshow(binim);
figure;
end
Either you revert to Matlab or you can always translate the code :)
Good luck
I may be late here. But this might be useful for other people later on.
Take a look at this reporitory:
https://github.com/Utkarsh-Deshmukh/Fingerprint-Enhancement-Python
It performs Fingerprint Enhancement using oriented Gabor filters in python.
installation:
pip install fingerprint_enhancer
usage:
import fingerprint_enhancer # Load the library
img = cv2.imread('image_path', 0) # read input image
out = fingerprint_enhancer.enhance_Fingerprint(img) # enhance the fingerprint image
cv2.imshow('enhanced_image', out); # display the result
cv2.waitKey(0)
I'm currently working on a project where I need to display a processed live video capture. Therefore, I'm using something similar to this:
cv::VideoCapture cap(0);
if (!cap.isOpened())
return -1;
cap.set(CV_CAP_PROP_FRAME_WIDTH, 1280);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 720);
cv::namedWindow("Current Capture");
for (;;)
{
cv::Mat frame;
cap >> frame;
cv::Mat mirrored;
cv::flip(frame, mirrored, 1);
cv::imshow("Current Capture", process_image(mirrored));
if (cv::waitKey(30) >= 0) break;
}
The problem I have is, that process_image, which perfomes a circle detection in the image, needs some time to finish and causes the displaying to be rather a slideshow then a video.
My Question is: How can I speed up the processing without manipulating the process_image function?
I thought about performing the image processing in another thread, but I'm not really sure how to start. Do you have any other idea than this?
PS.: I'm not expecting you to write code for me, I only need a point to start from ;)
EDIT:
Ok, if there is nothing i can do about the performance while capturing, I will need to change the process_image function.
cv::Mat process_image(cv::Mat img)
{
cv::Mat hsv;
cv::medianBlur(img, img, 7);
cv::cvtColor(img, hsv, cv::COLOR_BGR2HSV);
cv::Mat lower_hue_range; // lower and upper hue range in case of red color
cv::Mat upper_hue_range;
cv::inRange(hsv, cv::Scalar(LOWER_HUE1, 100, 100), cv::Scalar(UPPER_HUE1, 255, 255), lower_hue_range);
cv::inRange(hsv, cv::Scalar(LOWER_HUE2, 100, 100), cv::Scalar(UPPER_HUE1, 255, 255), upper_hue_range);
/// Combine the above two images
cv::Mat hue_image;
cv::addWeighted(lower_hue_range, 1.0, upper_hue_range, 1.0, 0.0, hue_image);
/// Reduce the noise so we avoid false circle detection
cv::GaussianBlur(hue_image, hue_image, cv::Size(13, 13), 2, 2);
/// store all found circles here
std::vector<cv::Vec3f> circles;
cv::HoughCircles(hue_image, circles, CV_HOUGH_GRADIENT, 1, hue_image.rows / 8, 100, 20, 0, 0);
for (size_t i = 0; i < circles.size(); i++)
{
/// circle center
cv::circle(hsv, cv::Point(circles[i][0], circles[i][1]), 3, cv::Scalar(0, 255, 0), -1, 8, 0);
/// circle outline
cv::circle(hsv, cv::Point(circles[i][0], circles[i][1]), circles[i][2], cv::Scalar(0, 0, 255), 3, 8, 0);
}
cv::Mat newI;
cv::cvtColor(hsv, newI, cv::COLOR_HSV2BGR);
return newI;
}
Is there a huge perfomance issue I can do anything about?
If you are sure that the process_image function is what is causing the bottle neck in your program, but you can't modify it, then there's not really a lot you can do. If that function takes longer to execute than the duration of a video frame then you will never get what you need.
How about reducing the quality of the video capture or reducing the size? At the moment I can see you have it set to 1280*720. If the process_image function has less data to work with it should execute faster.
I'm introducing myself in OpenCV (in order for an software project at university) and found a tutorial for color circle detection which I adapted and tested. It was written with OpenCV 1 in C. So I tried to convert it to OpenCv 2 classes API and everything was fine, but I ran into one problem:
The C function cvHoughCircles produces other results than the C++ function HoughCircles.
The C version finds my test circle and has a low rate of false positives, but the C++ version has a significantly higher mistake rate.
//My C implementation
IplImage *img = cvQueryFrame( capture );
CvSize size = cvGetSize(img);
IplImage *hsv = cvCreateImage(size, IPL_DEPTH_8U, 3);
cvCvtColor(img, hsv, CV_BGR2HSV);
CvMat *mask = cvCreateMat(size.height, size.width, CV_8UC1);
cvInRangeS(hsv, cvScalar(107, 61, 0, 0), cvScalar(134, 255, 255, 0), mask);
/* Copy mask into a grayscale image */
IplImage *hough_in = cvCreateImage(size, 8, 1);
cvCopy(mask, hough_in, NULL);
cvSmooth(hough_in, hough_in, CV_GAUSSIAN, 15, 15, 0, 0);
cvShowImage("mask",hough_in);
/* Run the Hough function */
CvMemStorage *storage = cvCreateMemStorage(0);
CvSeq *circles = cvHoughCircles(hough_in, storage, CV_HOUGH_GRADIENT,
4, size.height/4, 100, 40, 0, 0);
// ... iterating over all found circles
this works pretty well
//My C++ implementation
cv::Mat img;
cap.read(img);
cv::Size size(img.cols,img.rows);
cv::Mat hsv(size, IPL_DEPTH_8U, 3);
cv::cvtColor(img, hsv, CV_BGR2HSV);
cv::Mat mask(size.height, size.width, CV_8UC1);
cv::inRange(hsv, cv::Scalar(107, 61, 0, 0), cv::Scalar(134, 255, 255, 0), mask);
GaussianBlur( mask, mask, cv::Size(15, 15), 0, 0 );
/* Run the Hough function */
imshow("mask",mask);
vector<cv::Vec3f> circles;
cv::HoughCircles(mask, circles, CV_HOUGH_GRADIENT,
4, size.height/4, 100, 140, 0, 0);
// ... iterating over all found circles
As you can see, I use same arguments to all calls. I tested this with a webcam and a static sample object.One requirement is to use OpenCV2 C++ API.
Does anybody know, why I get so different results under equivalent conditions?
Edit
The different threshold values was just a mistake when I tested to make results more equally. These screenshots are taken with threshold set to 40 for both versions:
Screenshots: (Sorry, cannot yet post images)
C and C++ version
I see Hough parameters in C version as "..., 100, 40, 0, 0); " while in C++ version as "... 100, 140, 0, 0);" This difference in thresholds probably explains the difference in results.