工作流程比较两个图像中的重叠?

时间:2015-09-20 03:30:26

标签: image matlab image-processing

我将不得不提前为这个问题的模糊性道歉。我想帮助一位试图比较两张照片中荧光神经重叠的朋友。

设置如下: 有一个神经和背景标记为红色的图像,相同的神经和背景图像标记为绿色。有些神经只标有红色,有些只标有绿色,这很重要。我们想要做的是覆盖红色图像和绿色图像,然后找出哪两个神经标记(红色和绿色重叠)。

两个标签都有一个连续的强度(因此有明亮的红色和红色斑点的明显线条,绿色相同)。

我在想你能做的是设置红色的阈值强度,并仅用那些达到阈值强度的神经重新绘制图像。你也可以为绿色做这件事。然后,通过输出,您可以通过测量另一个输出中的一个输出中神经组织的百分比来比较重叠神经的比例。

能够生成输出图像是理想的,其中重叠区域可以是彩色的(例如蓝色)。然后,我们可以将所有重叠都显示为蓝色的输出,并将其覆盖在原始红/绿图像上,以便在视觉上突出显示重叠的神经。

或者(或组合),您可以将图像转换为字符串,然后在这些字符串中的相同位置查找匹配的字符。

这些都远远超出我的技能水平^ _ ^;

如果有人认为这是可能的,有任何更好的工作流程的建议,或者可以指向一些好的阅读方式或一个包来解决这个问题,我们将非常感激。

感谢您提供的任何帮助!

编辑:Matlab中的这个建议回答了我认为的问题的开始(如何测量哪些像素超过某个阈值强度)。它们转换为灰度,然后将强度视为白色的像素。然后,我需要生成仅满足阈值强度的像素的输出。

http://www.mathworks.com/matlabcentral/answers/86484-how-to-find-the-intensity-of-each-pixel-of-an-image

2 个答案:

答案 0 :(得分:3)

正如@JanEglinger建议的那样,没有必要使用(或支付)Matlab,特别是如果你的编程技巧有限。

我建议ImageMagick免费安装在大多数Linux发行版上,也可以从here用于OSX和Windows。然后,您可以从命令行完成您想要执行的操作,无需编译器或开发环境以及陡峭的学习曲线。

让我们先拍摄你的红色图像,只需使用终端中的命令行,我们就可以查看这样的统计数据:

identify -verbose red.jpg | more

Image: red.jpg
  Format: JPEG (Joint Photographic Experts Group JFIF format)
  Mime type: image/jpeg
  Class: DirectClass
  Geometry: 100x100+0+0
  Resolution: 72x72
  Print size: 1.38889x1.38889
  Units: PixelsPerInch
  Type: TrueColor
  Endianess: Undefined
  Colorspace: sRGB
  Depth: 8-bit
  Channel depth:
    red: 8-bit
    green: 8-bit
    blue: 8-bit
  Channel statistics:
    Pixels: 10000
    Red:
      min: 8 (0.0313725)
      max: 196 (0.768627)                                 <--- Good stuff in Red channel
      mean: 46.1708 (0.181062)
      standard deviation: 19.4835 (0.0764057)
    Green:
      min: 0 (0)
      max: 13 (0.0509804)                                 <--- Nothing much in Green channel
      mean: 3.912 (0.0153412)
      standard deviation: 1.69117 (0.00663204)
    Blue:
      min: 0 (0)
      max: 23 (0.0901961)                                 <--- Nothing much in Blue channel
      mean: 4.3983 (0.0172482)
      standard deviation: 2.88733 (0.0113229)

并且看到红色频道以外几乎没有任何用途的信息。那么,我们可以将它分成3个红色,绿色和蓝色通道,并丢弃绿色和蓝色通道,如下所示:

convert red.jpg -separate -delete 1,2 justRed.jpg

给了我们这个

enter image description here

对比度不是很好但是因为它只有8-196而不是0-255,所以我们可以将其标准化到整个范围,然后将阈值设置为50%,如下所示:

convert red.jpg -separate -delete 1,2 -normalize -threshold 50% r.jpg

给出了这个:

enter image description here

如果我们现在想要为您的绿色图像执行相同操作,我们会这样做,但这次删除红色和蓝色通道:

convert green.jpg -separate -delete 0,2 -normalize -threshold 50% g.jpg

给出这个:

enter image description here

最后,我们采用分离的,标准化的,阈值化的红色和绿色,并合成一个相同大小的空蓝色通道,并将它们全部放在一起作为新图像的红色,绿色和蓝色通道:

convert r.jpg g.jpg -size 100x100 xc:black -combine result.jpg

这给了我们这个我们在黄色区域看到的明亮的红色和绿色。

enter image description here

整个过程实际上只是在终端输入3行:

convert red.jpg   -separate -delete 1,2 -normalize -threshold 50% r.jpg
convert green.jpg -separate -delete 0,2 -normalize -threshold 50% g.jpg
convert r.jpg g.jpg -size 100x100 xc:black -combine result.jpg

如果你喜欢这种方法,你可以改变百分比,你可以引入降噪,实际上在一个更复杂的命令中完成所有操作,没有中间文件。无论如何,我向你推荐ImageMagick,即使你必须使用Matlab,也许ImageMagick中的这个例子会给你一些工作流程的指示。

额外示例...如果您为红色通道设置较低的阈值,您将在输出文件中获得更多红色像素,因此如果您将红色阈值更改为30%,您将得到:

enter image description here

答案 1 :(得分:1)

我一直在学习一些OpenCV,它是免费的,适用于OSX,Linux和Windows。我认为这可能会为你的问题增加一些互动性,所以我实现了与ImageMagick中完全相同的算法,但在我的初学者OpenCV中。如果更有经验的人对我的代码有任何建设性的指导方针,我会全力以赴。

无论如何,它在运行时看起来像这样,你可以滑动阈值滑块:

enter image description here

以下是代码:

////////////////////////////////////////////////////////////////////////////////
// NerveView.cpp
// Mark Setchell
//
// OpenCV program that takes two images as parameters, the first the red 
// fluorescent nerve image and the second which is the green image.
//
// The two images are resized, normalised and then displayed merged into a 
// single RGB image where the thresholds on red and green are controlled by
// sliders. Common areas therefore appear in yellow. Move either slider left
// to lower the threshold and therefore include more of that colour in the 
// combined output image, or move slider right to decrease amount of that
// colour.
//
// Run with:
//
// ./NerveView red.jpg green.jpg
//
// Compile with:
//
// g++ `pkg-config --cflags --libs opencv` NerveView.cpp -o NerveView
//
////////////////////////////////////////////////////////////////////////////////

#include <sstream>
#include <string>
#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <stdlib.h>
#include <stdio.h>

using namespace std;
using namespace cv;

int main(int argc, char** argv) {

    // Temp workspace
    Mat tmp1,tmp2;

    // Image size
    Size size(640,480);

    // Create a window for controls
    namedWindow("Controls", CV_WINDOW_NORMAL);
    resizeWindow("Controls",640,100);

    // Create slider to change Red threshold
    int RedThreshold = 50;
    createTrackbar("Red Threshold Percentage", "Controls", &RedThreshold, 100);

    // Create slider to change Green threshold
    int GreenThreshold = 50;
    createTrackbar("Green Threshold Percentage", "Controls", &GreenThreshold, 100);

    // Create variables to store input images and load them
    Mat Red,Green;
    Mat planes[3];

    // Load red image, split, discard G & B, resize, normalize
    tmp1   = imread(argv[1], CV_LOAD_IMAGE_COLOR);
    split(tmp1,planes);
    resize(planes[2],tmp1,size);
    normalize(tmp1,Red,0,255,NORM_MINMAX,CV_8UC1);

    // Load green image, split, discard R & B, resize, normalize
    tmp1   = imread(argv[2], CV_LOAD_IMAGE_COLOR);
    split(tmp1,planes);
    resize(planes[1],tmp1,size);
    normalize(tmp1,Green,0,255,NORM_MINMAX,CV_8UC1);

    // Make empty Blue channel, same size
    Mat Blue=Mat::zeros(size,CV_8UC1);

    //Create window to display images
    cv::namedWindow("Image", CV_WINDOW_AUTOSIZE);

    // Create variable to store the processed image
    Mat img=Mat::zeros(640,480,CV_8UC3);

    while (true){

    // Get thresholds, apply to their channels and combine to form result
        threshold(Red,tmp1,(RedThreshold*255)/100,255,THRESH_BINARY);
        threshold(Green,tmp2,(GreenThreshold*255)/100,255,THRESH_BINARY);

        // Combine B, G and R channels into "img"
        vector<Mat> channels;
        channels.push_back(Blue);
        channels.push_back(tmp2);
        channels.push_back(tmp1);
        merge(channels,img);

        // Display result
        imshow("Image",img);

        // See if user pressed a key
        int key=cvWaitKey(50);
        if(key>=0)break;
    }
    return 0;
}

关键词:神经,神经,荧光