我需要过滤一个数组来删除低于某个阈值的元素.我目前的代码是这样的:
threshold = 5
a = numpy.array(range(10)) # testing data
b = numpy.array(filter(lambda x: x >= threshold, a))
Run Code Online (Sandbox Code Playgroud)
问题是这会创建一个临时列表,使用带有lambda函数的过滤器(慢).
由于这是一个非常简单的操作,也许有一个numpy函数以有效的方式完成它,但我一直无法找到它.
我认为实现这一目标的另一种方法可能是对数组进行排序,找到阈值的索引并从该索引返回切片,但即使这对于小输入来说会更快(并且无论如何都不会引人注意) ),随着输入大小的增加,其最终渐近渐弱的效率.
有任何想法吗?谢谢!
更新:我也进行了一些测量,当输入为100.000.000个条目时,排序+切片仍然比纯python过滤器快两倍.
In [321]: r = numpy.random.uniform(0, 1, 100000000)
In [322]: %timeit test1(r) # filter
1 loops, best of 3: 21.3 s per loop
In [323]: %timeit test2(r) # sort and slice
1 loops, best of 3: 11.1 s per loop
In [324]: %timeit test3(r) # boolean indexing
1 loops, best of 3: 1.26 s per loop
Run Code Online (Sandbox Code Playgroud) 我使用的是一个固定的门槛,但事实证明这对我来说并不是那么好.然后,有人告诉我关于otsu门槛的事.如何在我的代码中使用它?我读到了它,我不太了解.有人可以向我解释如何在OpenCV中使用otsu阈值吗?
这是我现在的代码:
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main ( int argc, char **argv )
{
Mat im_gray = imread("img3.jpg",CV_LOAD_IMAGE_GRAYSCALE);
Mat im_rgb = imread("img3.jpg");
cvtColor(im_rgb,im_gray,CV_RGB2GRAY);
Mat img_bw = im_gray > 115;
imwrite("img_bw3.jpg", img_bw);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
有了这个,我必须将阈值更改为我想要转换为二进制的任何图像.我找到了这个:
cvThreshold(scr, dst, 128, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
Run Code Online (Sandbox Code Playgroud)
是对的吗?我不太了解,因此,我不知道如何适应我的代码.
什么是快速可靠的阈值图像可能模糊和不均匀亮度的方法?
示例(模糊但亮度均匀):

由于不保证图像具有均匀的亮度,因此使用固定阈值是不可行的.自适应阈值可以正常工作,但由于模糊,它会在特征中产生断裂和扭曲(这里,重要的特征是数独数字):

我也尝试过使用直方图均衡(使用OpenCV的equalizeHist功能).它可以增加对比度而不会降低亮度差异.
我发现的最佳解决方案是将图像按其形态结束(信用到此帖子)来划分,使亮度均匀,然后重新归一化,然后使用固定阈值(使用Otsu算法选择最佳阈值水平):

以下是OpenCV for Android中的代码:
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(19,19));
Mat closed = new Mat(); // closed will have type CV_32F
Imgproc.morphologyEx(image, closed, Imgproc.MORPH_CLOSE, kernel);
Core.divide(image, closed, closed, 1, CvType.CV_32F);
Core.normalize(closed, image, 0, 255, Core.NORM_MINMAX, CvType.CV_8U);
Imgproc.threshold(image, image, -1, 255, Imgproc.THRESH_BINARY_INV
+Imgproc.THRESH_OTSU);
Run Code Online (Sandbox Code Playgroud)
这很有效,但关闭操作非常慢.减小结构元素的尺寸会增加速度但会降低精度.
编辑:根据DCS的建议,我尝试使用高通滤波器.我选择了拉普拉斯滤波器,但我希望Sobel和Scharr滤波器具有相似的结果.滤波器在不包含特征的区域中拾取高频噪声,并且由于模糊而遭受与自适应阈值类似的失真.它也需要与关闭操作一样长.以下是15x15过滤器的示例:

编辑2:根据AruniRC的回答,我使用建议的参数在图像上使用Canny边缘检测:
double mean = Core.mean(image).val[0];
Imgproc.Canny(image, image, 0.66*mean, 1.33*mean);
Run Code Online (Sandbox Code Playgroud)
我不确定如何可靠地自动微调参数以获得连接的数字.

我有一个相当模糊的数独谜题的432x432图像,其自适应阈值不好(取5x5像素的块大小,然后减去2):

正如你所看到的,数字略有扭曲,其中有很多破损,而且有5s融入6s和6s融入8s.此外,还有很多噪音.为了修复噪声,我必须使用高斯模糊使图像更加模糊.然而,即使是相当大的高斯内核和自适应阈值blockSize(21x21,减去2)也无法消除所有断点并将数字融合在一起甚至更多:

我还尝试在阈值处理后扩展图像,这与增加blockSize有类似的效果; 并且锐化图像,这在某种程度上没有太大作用.我还应该尝试什么?
我使用scikit-learn训练了ExtraTreesClassifier(gini索引),它非常适合我的需求.准确性不是很好,但使用10倍交叉验证,AUC为0.95.我想在我的工作中使用这个分类器.我对ML很新,所以如果我问你一些概念错误的话,请原谅我.
我绘制了一些ROC曲线,通过它,我似乎有一个特定的阈值,我的分类器开始表现良好.我想在拟合的分类器上设置这个值,所以每次我调用预测时,分类器都会使用该阈值,我可以相信FP和TP的速率.
我也来到这篇文章(scikit .predict()默认阈值),其中声明阈值不是分类器的通用概念.但由于ExtraTreesClassifier的方法是predict_proba,并且ROC曲线也与thresdholds定义有关,所以在我看来我应该可以指定它.
我没有找到任何参数,也没有找到任何类/接口来实现它.如何使用scikit-learn为训练有素的ExtraTreesClassifier(或任何其他人)设置阈值?
非常感谢,科利斯
在Opencv的python包装器中有任何方法/函数可以在二进制图像中找到黑色区域吗?(就像Matlab中的regionprops)到目前为止,我加载了我的源图像,通过阈值将其转换为二进制图像,然后将其反转以突出显示黑色区域(现在是白色).
我不能使用第三方库,如cvblobslob或cvblob
我有8位灰度TIFF图像,我想使用75%白色(十进制190)阈值转换为单色.在Image.convert(模式)方法部分,PIL手册说:
"将灰度图像转换为位级图像(模式"1")时,所有非零值都设置为255(白色).要使用其他阈值,请使用点法."
Image.point(table)方法表示它通过给定的表映射每个像素.
im.point(table,mode)=> image
im.point(function,mode)=> image"通过表格映射图像,并在飞行中进行转换.在当前版本的PIL中,这只能用于在一步中将'L'和'P'图像转换为'1',例如对图像进行阈值处理."
如何创建与我需要的75%阈值相对应的表(或函数)?
我有这个灰色的视频流:

该图像的直方图:

阈值图像由:
threshold( image, image, 150, 255, CV_THRESH_BINARY );
Run Code Online (Sandbox Code Playgroud)
我得到:

我所期待的.
当我做自适应阈值处理时:
adaptiveThreshold(image, image,255,ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY,15,-5);
Run Code Online (Sandbox Code Playgroud)
我得到:

这看起来像边缘检测而不是阈值.我所期待的是黑白区域.所以我的问题是,为什么这看起来像边缘检测而不是阈值.
thx提前
我正在编写一个应用程序,涉及使用一个手指在屏幕上书写,或最终使用手写笔.我有那个部分在工作.在ACTION_DOWN上,开始绘图; 在ACTION_MOVE上,添加线段; 在ACTION_UP上,完成一行.
问题是在ACTION_DOWN之后,显然指针需要从它开始的位置移动超过10个像素(基本上是起始点周围的20x20框)才能开始发送ACTION_MOVE事件.离开盒子后,移动事件都非常准确.(我通过测试得出10像素的东西.)因为这是用于书写或绘图,10像素是一个相当大的损失:取决于你试图写的小,你可能会失去第一个字母或两个.我还没有找到任何关于它的信息 - 只有一两个论坛上的帖子,比如http://android.modaco.com/topic/339694-touch-input-problem-not-detecting-very-small -movements/page_ pid _1701028#entry1701028.它似乎出现在某些设备或系统上,而不是其他设备或系统上.但是,当你拥有它时,没有关于如何摆脱它的想法.
我正在使用带有Android 3.1的Galaxy Tab 10.1.我已经尝试了几种不同的东西试图摆脱它:我已经尝试将事件的坐标设置为其他东西,看看我是否可以欺骗它以为光标位于不同的位置; 我尝试用更改的坐标重新调度事件(我的处理程序对新点做出反应,但仍然没有响应10像素半径的移动.)我在源代码中搜索了对该效果的任何引用,并且没有找到(虽然我认为它来自不同版本的Android - 3.1的代码尚未发布,是吗?)我已经搜索了查询指针当前状态的方法,所以我可以只有一个计时器捕获更改,直到指针超过阈值.没有相应的移动事件,找不到任何获得指针坐标的方法.没有任何效果.有没有人知道这件事,或有任何想法或解决方法?谢谢.
- 更新:拖放事件显示相同的阈值.
我的问题是:对于图像中对象周围的边界框,我有ROI。ROI是由Faster R-CNN获得的。现在,我要应用阈值处理,以将对象准确地包含在边界框中。该图像的投资回报率由Faster RCNN获得。
因此,在获得ROI之后,我只从图像中选择了ROI并粘贴到相同大小和尺寸的黑色图像上,从而得到以下图像。
如您所见,方框是矩形的,因此在某些地方它会覆盖一些背景区域以及尖峰。因此,如何应用阈值处理以仅使尖峰和其他像素变为黑色?
编辑:我已将链接添加到问题中第一张图片的ROI文本文件中