opencv C++ 中非均匀光照物体的检测
Detection of objects in nonuniform illumination in opencv C++
我正在使用 OpenCV C++ 在 video/live stream/image 中执行特征检测。视频不同部分的光照条件不同,导致在将 RGB 图像转换为二进制图像时某些部分被忽略。
视频特定部分的照明条件也会随着视频的播放而变化。我尝试了 'Histogram equalization' 函数,但它没有帮助。
我在 MATLAB 中得到了一个可行的解决方案 link:
http://in.mathworks.com/help/images/examples/correcting-nonuniform-illumination.html
但是,上述 link 中使用的大多数函数在 OpenCV 中不可用。
您能否建议在 OpenCV C++ 中替代此 MATLAB 代码?
OpenCV 具有框架中可用的自适应阈值范例:http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#adaptivethreshold
函数原型如下:
void adaptiveThreshold(InputArray src, OutputArray dst,
double maxValue, int adaptiveMethod,
int thresholdType, int blockSize, double C);
前两个参数是输入图像和存储输出阈值图像的位置。 maxValue
是分配给通过标准的输出像素的阈值,adaptiveMethod
是用于自适应阈值的方法,thresholdType
是您要执行的阈值类型(更多稍后),blockSize
是要检查的 windows 的大小(稍后会详细介绍),C
是要从每个 window 中减去的常数。我从来没有真正需要使用它,我通常将它设置为 0。
adaptiveThreshold
的默认方法是分析 blockSize x blockSize
windows 并计算此 window 中的平均强度减去 C
。如果这个window的中心在平均强度之上,则输出图像输出位置中的这个对应位置设置为maxValue
,否则相同位置设置为0。这应该打击非- 均匀照明问题,您不是对图像应用全局阈值,而是对局部像素邻域执行阈值处理。
您可以阅读有关其他参数的其他方法的文档,但要开始使用,您可以这样做:
// Include libraries
#include <cv.h>
#include <highgui.h>
// For convenience
using namespace cv;
// Example function to adaptive threshold an image
void threshold()
{
// Load in an image - Change "image.jpg" to whatever your image is called
Mat image;
image = imread("image.jpg", 1);
// Convert image to grayscale and show the image
// Wait for user key before continuing
Mat gray_image;
cvtColor(image, gray_image, CV_BGR2GRAY);
namedWindow("Gray image", CV_WINDOW_AUTOSIZE);
imshow("Gray image", gray_image);
waitKey(0);
// Adaptive threshold the image
int maxValue = 255;
int blockSize = 25;
int C = 0;
adaptiveThreshold(gray_image, gray_image, maxValue,
CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY,
blockSize, C);
// Show the thresholded image
// Wait for user key before continuing
namedWindow("Thresholded image", CV_WINDOW_AUTOSIZE);
imshow("Thresholded image", gray_image);
waitKey(0);
}
// Main function - Run the threshold function
int main( int argc, const char** argv )
{
threshold();
}
adaptiveThreshold
应该是你的首选。
但是我在这里报告 "translation" 从 Matlab 到 OpenCV,这样你就可以很容易地移植你的代码。如您所见,大多数功能在 Matlab 和 OpenCV 中都可用。
#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
// Step 1: Read Image
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
// Step 2: Use Morphological Opening to Estimate the Background
Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(15,15));
Mat1b background;
morphologyEx(img, background, MORPH_OPEN, kernel);
// Step 3: Subtract the Background Image from the Original Image
Mat1b img2;
absdiff(img, background, img2);
// Step 4: Increase the Image Contrast
// Don't needed it here, the equivalent would be cv::equalizeHist
// Step 5(1): Threshold the Image
Mat1b bw;
threshold(img2, bw, 50, 255, THRESH_BINARY);
// Step 6: Identify Objects in the Image
vector<vector<Point>> contours;
findContours(bw.clone(), contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
for(int i=0; i<contours.size(); ++i)
{
// Step 5(2): bwareaopen
if(contours[i].size() > 50)
{
// Step 7: Examine One Object
Mat1b object(bw.size(), uchar(0));
drawContours(object, contours, i, Scalar(255), CV_FILLED);
imshow("Single Object", object);
waitKey();
}
}
return 0;
}
我正在使用 OpenCV C++ 在 video/live stream/image 中执行特征检测。视频不同部分的光照条件不同,导致在将 RGB 图像转换为二进制图像时某些部分被忽略。
视频特定部分的照明条件也会随着视频的播放而变化。我尝试了 'Histogram equalization' 函数,但它没有帮助。
我在 MATLAB 中得到了一个可行的解决方案 link:
http://in.mathworks.com/help/images/examples/correcting-nonuniform-illumination.html
但是,上述 link 中使用的大多数函数在 OpenCV 中不可用。
您能否建议在 OpenCV C++ 中替代此 MATLAB 代码?
OpenCV 具有框架中可用的自适应阈值范例:http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#adaptivethreshold
函数原型如下:
void adaptiveThreshold(InputArray src, OutputArray dst,
double maxValue, int adaptiveMethod,
int thresholdType, int blockSize, double C);
前两个参数是输入图像和存储输出阈值图像的位置。 maxValue
是分配给通过标准的输出像素的阈值,adaptiveMethod
是用于自适应阈值的方法,thresholdType
是您要执行的阈值类型(更多稍后),blockSize
是要检查的 windows 的大小(稍后会详细介绍),C
是要从每个 window 中减去的常数。我从来没有真正需要使用它,我通常将它设置为 0。
adaptiveThreshold
的默认方法是分析 blockSize x blockSize
windows 并计算此 window 中的平均强度减去 C
。如果这个window的中心在平均强度之上,则输出图像输出位置中的这个对应位置设置为maxValue
,否则相同位置设置为0。这应该打击非- 均匀照明问题,您不是对图像应用全局阈值,而是对局部像素邻域执行阈值处理。
您可以阅读有关其他参数的其他方法的文档,但要开始使用,您可以这样做:
// Include libraries
#include <cv.h>
#include <highgui.h>
// For convenience
using namespace cv;
// Example function to adaptive threshold an image
void threshold()
{
// Load in an image - Change "image.jpg" to whatever your image is called
Mat image;
image = imread("image.jpg", 1);
// Convert image to grayscale and show the image
// Wait for user key before continuing
Mat gray_image;
cvtColor(image, gray_image, CV_BGR2GRAY);
namedWindow("Gray image", CV_WINDOW_AUTOSIZE);
imshow("Gray image", gray_image);
waitKey(0);
// Adaptive threshold the image
int maxValue = 255;
int blockSize = 25;
int C = 0;
adaptiveThreshold(gray_image, gray_image, maxValue,
CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY,
blockSize, C);
// Show the thresholded image
// Wait for user key before continuing
namedWindow("Thresholded image", CV_WINDOW_AUTOSIZE);
imshow("Thresholded image", gray_image);
waitKey(0);
}
// Main function - Run the threshold function
int main( int argc, const char** argv )
{
threshold();
}
adaptiveThreshold
应该是你的首选。
但是我在这里报告 "translation" 从 Matlab 到 OpenCV,这样你就可以很容易地移植你的代码。如您所见,大多数功能在 Matlab 和 OpenCV 中都可用。
#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
// Step 1: Read Image
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
// Step 2: Use Morphological Opening to Estimate the Background
Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(15,15));
Mat1b background;
morphologyEx(img, background, MORPH_OPEN, kernel);
// Step 3: Subtract the Background Image from the Original Image
Mat1b img2;
absdiff(img, background, img2);
// Step 4: Increase the Image Contrast
// Don't needed it here, the equivalent would be cv::equalizeHist
// Step 5(1): Threshold the Image
Mat1b bw;
threshold(img2, bw, 50, 255, THRESH_BINARY);
// Step 6: Identify Objects in the Image
vector<vector<Point>> contours;
findContours(bw.clone(), contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
for(int i=0; i<contours.size(); ++i)
{
// Step 5(2): bwareaopen
if(contours[i].size() > 50)
{
// Step 7: Examine One Object
Mat1b object(bw.size(), uchar(0));
drawContours(object, contours, i, Scalar(255), CV_FILLED);
imshow("Single Object", object);
waitKey();
}
}
return 0;
}