如何检测以下图像中的黑点?(我只粘贴一个测试图像,使问题看起来很紧凑.可以找到更多图像→这里←).

如上所示,背景颜色大致为蓝色,点颜色为"黑色".如果选择一个黑色像素并测量其RGB颜色,则该值可以是
(0,44,65)或
(14,69,89)....因此,我们不能设置一个范围来告诉像素是黑点或背景的一部分.
我测试了10张不同颜色的图像,但我希望我能找到一种方法来检测可能由三种或更多颜色组成的更复杂背景中的黑点,只要人眼可以轻松识别黑点.可以省略一些极小或模糊的点.
上个月,我在stackoverflow上问了一个类似的问题,但是没有一个完美的解决方案,但是有一些很好的答案.如果您有兴趣,请详细了解我的工作.
以下是我尝试过的方法:
转换为灰度或图像的亮度.困难在于我无法找到进行二值化的自适应阈值.显然,将彩色图像转换为灰度或使用亮度(HSV)将失去许多有用的信息.计算自适应阈值的Otsu算法也不起作用.
计算RGB直方图.在我的上一个问题中,natan的方法是通过直方图估计黑色.节省时间,但自适应阈值也是一个问题.
聚类.我尝试过k-means聚类,发现它对于只有一种颜色的背景非常有效.缺点(参见我自己的答案)是我需要提前设置聚类中心的数量,但我不知道背景如何.更重要的是,它太慢了!我的应用程序是在iPhone上实时捕获,现在它可以使用k-means每秒处理7~8帧(我认为20 FPS是好的).
我认为不仅相似的颜色而且相邻的像素应该"聚集"或"合并"以便提取黑点.请指导我解决问题的正确方法.任何建议或算法将不胜感激.没有免费的午餐,但我希望在成本和准确性之间做出更好的平衡.
我正在使用FFT从音频文件中提取每个频率分量的幅度.实际上,Audacity中已经有一个名为Plot Spectrum的函数可以帮助解决问题.以3kHz正弦和6kHz正弦组成的音频文件为例,频谱结果如下图所示.你可以看到峰值在3KHz和6kHz,没有额外的频率.
现在我需要实现相同的功能并在Python中绘制类似的结果.我在帮助下接近Audacity结果,rfft但在得到这个结果后仍然有问题需要解决.
相关代码:
import numpy as np
from pylab import plot, show
from scipy.io import wavfile
sample_rate, x = wavfile.read('sine3k6k.wav')
fs = 44100.0
rfft = np.abs(np.fft.rfft(x))
p = 20*np.log10(rfft)
f = np.linspace(0, fs/2, len(p))
plot(f, p)
show()
Run Code Online (Sandbox Code Playgroud)
更新
我将Hanning窗口与整个长度信号相乘(这是正确的吗?)并得到它.裙子的大部分幅度都低于40.
并按照@Mateen Ulhaq的说法将y轴缩放为分贝.结果更接近Audacity one.我可以将低于-90dB的幅度处理得如此之低以至于可以忽略吗?
更新的代码:
fs, x = wavfile.read('input/sine3k6k.wav')
x = x * np.hanning(len(x))
rfft = np.abs(np.fft.rfft(x))
rfft_max = max(rfft)
p = 20*np.log10(rfft/rfft_max)
f = np.linspace(0, fs/2, len(p))
Run Code Online (Sandbox Code Playgroud)
关于赏金
通过上面更新中的代码,我可以用分贝测量频率分量.最高可能值为0dB.但该方法仅适用于特定的音频文件,因为它使用rfft_max此音频.我想像Audacity那样在一个标准规则中测量多个音频文件的频率成分. …
我的工作基于带有点阵的图像(图1),最终结果如图4所示.我将逐步解释我的工作.
图1原始图像

步骤1:检测每个对象的边缘,包括点和我想要删除的"环"以获得更好的性能.边缘检测的结果如图2所示.我使用Canny边缘探测器,但它对一些浅灰色点不起作用.我的第一个问题是如何关闭点的轮廓并尽可能减少其他噪音?
图2边缘检测

第2步:扩张每个对象.我找不到填补洞的好方法,所以我直接扩张它们.如图3所示,孔似乎扩大得太多,其他噪音也是如此.我的第二个问题是如何填充或扩大孔,以使它们以相同/相似的尺寸填充圆圈?
图3扩张

第3步:找到并绘制每个点的质心.如图4所示,由于粗略图像处理,存在"环"的标记,并且一些点以两个白色像素示出.想要的结果应该只显示一个点的点和一个白色像素.
图4:质心

这是我的这3个步骤的代码.任何人都可以帮助我的工作做得更好吗?
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
using namespace std;
using namespace cv;
// Global variables
Mat src, edge, dilation;
int dilation_size = 2;
// Function header
void thresh_callback(int, void*);
int main(int argc, char* argv)
{
IplImage* img = cvLoadImage("c:\\dot1.bmp", 0); // dot1.bmp = Fig. 1
// Perform canny edge detection
cvCanny(img, img, 33, 100, 3);
// IplImage to Mat …Run Code Online (Sandbox Code Playgroud) 人眼很容易从其他颜色中辨别出黑色.但电脑怎么样?
我在普通A4纸上打印了一些色块.由于有三种墨水组成彩色图像,青色,品红色和黄色,我设置每个块的颜色C = 20%,C = 30%,C = 40%,C = 50%,其余两种颜色这是我的源图像的第一列.到目前为止,没有黑色(CM of CMYK)墨水打印.之后,我设置每个点的颜色K = 100%,其余颜色为0以打印黑点.

你可能会觉得我的形象很奇怪而且可怕.实际上,图像放大30倍,可以清楚地看到墨水欺骗我们的眼睛.色条妨碍我识别这些黑点(点打印为800 dpi的一个像素).没有颜色背景,我习惯blur并且做canny edge detector了提取边缘.然而,当添加颜色背景时,由于条带,简单地做grayscale并且edge detector不能获得好的结果.为了解决这些问题,我的眼睛会怎样做?
我决定检查源图像的亮度.我参考了这篇文章和公式:
亮度= sqrt(0.299 R*R + 0.587 G*G + 0.114 B*B)

亮度更接近人类的感知,并且在黄色背景下效果非常好,因为与青色和品红色相比,黄色的亮度最高.但如何使青色和洋红色条带尽可能明亮?预期的结果是所有条带都消失了.
更复杂的图像:
C = 40%,M = 40%

C = 40%,Y = 40%

Y = 40%,M = 40%

FFT结果为C = 40%,Y = 40%亮度图像

任何人都可以给我一些提示去除色条?
@natan我试过你建议我的FFT方法,但我不幸在轴x和y都达到峰值.为了像你一样绘制频率,我将图像调整为正方形.


从C++调用我的MATLAB函数时遇到几个错误.主要思想是:首先编译MATLAB函数并生成DLL文件,然后在C++中包含.h和.lib文件.最后,编写.cpp来测试并调用该函数.这是我的详细步骤,请告诉我我哪里错了.
(使用MATLAB 2012b和Visual C++ 2008,Windows 7 64位)
在MATLAB中:
mbuild -setup并将mex -setupVisual Microsoft Visual C++ 2008 SP1设置为编译器.MyAdd.m在文件夹中创建,C:\Users\WangYudong\Documents\MATLAB\MyAdd_M功能如下:
function [c] = MyAdd(a, b)
c = a + b;
Run Code Online (Sandbox Code Playgroud)mcc -W cpplib:libMyAdd -T link:lib MyAdd编译MyAdd.m并生成多个文件,包括libMyAdd.dll,libMyAdd.h,libMyAdd.lib和其他文件.
在C++中
选择VC++目录 → 包括要添加的文件E:\MATLAB\R2012b\extern\include.
选择VC++目录 → 库文件添加
E:\MATLAB\R2012b\extern\lib\win64\microsoft和
C:\Users\WangYudong\Documents\MATLAB\MyAdd_M.
选择链接器 → 输入 → 附加依赖项以添加新条目:
mclmcr.lib
mclmcrrt.lib
libmx.lib
libmat.lib
libMyAdd.lib
Run Code Online (Sandbox Code Playgroud)创建一个新的MyAdd_test.cpp …
我正在处理如图1所示的图像,它由一系列点组成,需要转换成图2.
图1原始图像

图2想要的图像

为了完成转换,首先我检测edge每个点,然后进行操作dilation.选择合适的参数后,结果令人满意,如图3所示.
图3扩张后的图像

我在MATLAB之前处理过相同的图像.当将对象(图3中)缩小为像素时,功能bwmorph(Img,'shrink',Inf)起作用,结果正好是图2所示的结果.那么如何在opencv中获得相同的想要的图像?似乎没有类似的shrink功能.
这是我找到边缘和扩张操作的代码:
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
using namespace cv;
// Global variables
Mat src, dilation_dst;
int dilation_size = 2;
int main(int argc, char *argv[])
{
IplImage* img = cvLoadImage("c:\\001a.bmp", 0); // 001a.bmp is Fig.1
// Perform canny edge detection
cvCanny(img, img, 33, 100, 3);
// IplImage to Mat
Mat imgMat(img);
src = img;
// Create windows
namedWindow("Dilation Demo", CV_WINDOW_AUTOSIZE); …Run Code Online (Sandbox Code Playgroud) 我正在为Xcode/Swift开发适用于iPad/iPhone的游戏.
我需要做的是获得图像/轮廓的轮廓路径,以便我可以沿着图像/轮廓的轮廓设置动画.这就是为了创造一种激光切割效果,当你用激光切割机突破门/窗时,你会在电影中看到这种效果.
只是将它绘制为Beizer路径是行不通的,因为我需要为一堆图像/轮廓执行此操作.如果可能的话,我宁愿只是将图像添加到我的项目中并在代码中进行概述,这样我就可以轻松扩展更多的形状和大小.
在SpriteKit中,我尝试使用SKPhysicsBody,然后使用Alpha创建轮廓.这给了我那个轮廓但不是一条路径,所以我不能沿着这条线动画.实际上当启用".showsPhysics"时,我得到了我需要的线,但仍然不是我可以用于动画的线.
有没有办法使用/修改".showsPhysics"方法或将PhysicsBody转换为路径?
我在Swift编写代码,任何建议都会受到赞赏.
这是我需要的一个例子,我需要蓝线作为动画的路径.
假设我有一个 ViewController,FooViewController它有一个属性:
@property (nonatomic, strong) NSAttributedString *foo;
Run Code Online (Sandbox Code Playgroud)
我想在视图出现时更新 UI,所以viewDidLoad和 foosetter是这样的:
- (void)viewDidLoad
{
[super viewDidLoad];
self.foo = [[NSAttributedString alloc] initWithString:@"test" attributes:@{ NSForegroundColorAttributeName : [UIColor greenColor]} ];
}
- (void)setFoo:(NSAttributedString *)foo
{
_foo = foo;
if (self.view.window) [self updateUI];
}
Run Code Online (Sandbox Code Playgroud)
我预计updateUI当视图在屏幕上时会调用该方法,但事实并非如此。仅当我删除时if (self.view.window),才会调用该方法。这里有什么问题?
谢谢
我正在开发的 SpriteKit 游戏遇到了一些问题。我正在尝试做一个平台游戏风格的游戏,玩家点击屏幕让角色跳跃。我正在通过以下方式实现这一目标:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// reset the velocity each jump, so that a constant impulse is always applied
self.player.physicsBody.velocity = CGVectorMake(0, 0);
// jump the player up
[self.player.physicsBody applyImpulse:CGVectorMake(0, PLAYER_JUMP_HEIGHT)];
}
Run Code Online (Sandbox Code Playgroud)
PLAYER_JUMP_HEIGHT只是一个常数。我还设置了具有恒定质量的播放器。
这在 iPad 模拟器上非常有效,这是我进行大部分初始测试的地方。然而,在调整我的代码以适应设备分辨率(对于手机等)之后,我的物理性能似乎非常差,尤其是在 iPhone 4S 模拟器上。同样的冲动现在让玩家跳得非常高,而且他们似乎也更快地从平台等物体上掉下来,比以前更像线性曲线。
我通过首先设置场景的缩放模式来缩放我的场景以适应多个设备:
scene.scaleMode = SKSceneScaleModeResizeFill;
Run Code Online (Sandbox Code Playgroud)
我还想出了一种方法,通过将当前设备的分辨率与 iPad 的分辨率进行比较,然后除以得到一个比例因子来乘以所有内容,从而缩放游戏中的其他所有内容。因此,在 iPad 屏幕宽度为 2048 的情况下,如果我在 iPhone 4S 上运行,则比例因子将为 960 / 2048 = 0.46。通过这种方式,我可以使用一组常量来设计游戏,这些常量可以跨所有设备分辨率进行缩放,而不会出现其他缩放模式的裁剪或其他缩放问题。
我对这可能是什么感到非常困惑。我试过将玩家质量和跳跃高度乘以屏幕比例因子,在所有可能的组合中,都无济于事。我还尝试弄乱了physicsWorld 的重力和速度,这也不起作用。如果有人有处理这个问题的经验并愿意分享,任何帮助将不胜感激。谢谢!
我想检测下面图像的背景,其前景总是很多黑点:
img.png

有人使用磁盘形结构元素对图像执行形态学闭合,并获得良好的结果:

Matlab代码:
img = imread('c:\img.png');
bg = imclose(img, strel('disk', 15));
figure('name', 'bg'), imshow(bg);
Run Code Online (Sandbox Code Playgroud)
那么如何在opencv中实现imclose(IM,SE)来替换MATLAB中的工作,还是有另一种更好的方法来使用opencv方法检测这样的背景?
我正在研究一个球反弹并击中平台然后反弹回来的游戏。理想情况下,球应该反弹到它开始时的高度。然而,在我的比赛中,球会慢慢地弹得越来越高。我查看了文档并尝试更改所有物理属性,但似乎没有任何效果。
有什么建议?
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
let ballCategory:UInt32 = 0x1 << 0;
let circleCategory:UInt32 = 0x1 << 1;
let platformCategory:UInt32 = 0x1 << 2;
var ball = SKShapeNode(circleOfRadius: 20.0)
var circle = SKShapeNode(circleOfRadius: 200.0)
var platform = SKShapeNode(rectOfSize: CGSizeMake(10, 1))
var circleColor = 2
var ballColor = 3
var scoreLabel: SKLabelNode!
var score = 0
override func didMoveToView(view: SKView) {
setUpLabels()
self.physicsWorld.contactDelegate = self
backgroundColor = (UIColor.whiteColor())
ball.fillColor = SKColor.redColor()
ball.strokeColor = SKColor.clearColor()
ball.position = CGPoint(x: self.size.width/2, …Run Code Online (Sandbox Code Playgroud) 我需要生成这样一个32位二进制序列:它有8个'1',其余位是'0'.所以用十六进制编写,一些序列将是这样的:
000000FF
000001FE
000001FD
000001FB
000001F7
...
Run Code Online (Sandbox Code Playgroud)
问题是从32中选择8,因此有10518300种组合.换句话说,像我的例子一样有10518300个序列.如果您给我任何建议或算法来生成我想要的序列,我将不胜感激.
我想在我的应用程序中定义一些颜色.我对此有点新鲜,所以我不太确定在哪里放置我的颜色定义.
我可以将颜色定义为:
lightColor = [UIColor colorWithRed:48/255 green:160.0/255 blue:255.0/255 alpha:1.0];
Run Code Online (Sandbox Code Playgroud)
但是我在哪里放这个,以便在我的应用程序中使用它?
如果这是一个非常简单易懂的问题,请道歉,但我似乎无法在任何地方找到答案!