2012-02-24 13:11:15 lj695242104 阅读数 5899

描述:图像的减法即两幅输入图像同意位置像素相减,得到一个输出图像的过程。

公式描述:

O(i,j) = I1(i,j) - I2(i,j)  OR  O(i,j) = |I1(i,j) - I2(i,j)|

注意1:常值问题,输入图像也可以有一个是常量,即 O(i,j) = I(i,j) - C   OR  O(i,j) =| I(i,,j) - C|

注意2:下限问题,如果两幅图像相减得出的像素低于0,则一律统统归为0.

注意3:循环问题,如果图像格式支持循环问题,则不存在下限问题,即如果输出的像素为-20,则,系统自动把它变成236.


Code:

Similarity, displayed to the kernel function:

 /**
   *Applies the image difference operator on the specified image arrays, with the specified offset and scale value
   *@param src1_1d The first source image as a pixel array
   *@param src2_1d The second source image as a pixel array
   *@param width width of the destination image in pixels
   *@param height height of the destination image in pixels
   *@param oset The offset value
   *@param scale The scale value
   *@param reverse false if image2 - image 1
   *@return A pixel array containing the difference of the two input images
   */

  public int [] imagedifference(int [] src1_1d, int [] src2_1d, int width, int height, 
				float oset, float scale, boolean reverse){
    
    int place1 = -1;
    int place2 = -1;
    int src1rgb = 0;
    int src2rgb = 0;
    int diff = 0;

    d_w = width;
    d_h = height;
   

    dest_1d = new int[d_w*d_h];
   
    boolean firstwider = false;
    boolean secondwider = false;
    int wrap;
    
    if (i1_w > d_w){
      wrap =   ((i1_w + 1) - d_w);
      firstwider = true;
    } else if (i2_w > d_w){
      wrap =    ((i2_w + 1) - d_w);
      secondwider = true;
      
    } else {
      wrap = 0;
    }
   
    if (wrap == 0) {
      for (int i=0; i< dest_1d. length ; i++){
	src2rgb = src2_1d[i] & 0x000000ff;
	src1rgb = src1_1d[i] & 0x000000ff;
	if (!reverse) {
	  diff = (int)  ((scale * ((float) src2rgb - (float) src1rgb )) + oset);
	} else {
	  diff = (int)  ((scale * ((float) src1rgb - (float) src2rgb )) + oset);
	}

	if (diff < 0){
	  diff = 0;
	} else if  (diff > 255){
	  diff = 255;
	}
      

	dest_1d[i ] =  0xff000000 | (diff + (diff << 16) + (diff << 8));
       
      }
   
      return dest_1d;
  
    }
    else {
     
      for (int i=0; i< dest_1d. length ; i++){
   	
      if ((i %d_w  ) == 0 ) {
	if ( i == 0 ){
	  place1 = 0;
	  place2 = 0;
	} else if (secondwider) {
	  place2 = place2 + wrap;
	  place1 ++;
	} else {
	  place1 = place1 + wrap;
	  place2 ++;
	}
      } else{
	place2 ++;
	place1 ++;
      }
    
      src2rgb = src2_1d[place2] & 0x000000ff;
      src1rgb = src1_1d[place1] & 0x000000ff;
      
      if (!reverse) {
	diff = (int)  ((scale * ((float) src2rgb - (float) src1rgb )) + oset);
      } else {
	diff = (int)  ((scale * ((float) src1rgb - (float) src2rgb )) + oset);
      }
      //clip to 0 ... 255
      if (diff < 0){
	diff = 0;
      } else if  (diff > 255){
	diff = 255;
      }
      
      
      dest_1d[i ] =  0xff000000 | (diff + (diff << 16) + (diff << 8));
      }
      return dest_1d;
    }
  }

Input Image




Output Image




总结:减法操作作为图像基本运算中的一员,它的作用也是不容忽视的,特别是特征的提取这一领域,它的作用的巨大的。

2019-04-14 12:28:28 matt45m 阅读数 5180

前言

1.有一个小游戏,就给出两张内容几乎差不多全部相同的图像,让大家在最快的时间内找出两个图像中有几处不同地方,我这里试着用OpenCV实现这个功能。
2.我的编程环境是Windows 7 64位,IDE是VS2015,配置了OpenCV3.3与OpenCV_Contrib,实现语言是C++。是于如果配置以上的环境,可以看我之前写的博文。

一、资源准备

可以在网上搜《图片大找茬》,然后下载两张相似的图像,但图像的大小必须一样。下面是我指用的两张图像。如果不一样,就用resize()这个函数去调整两张图像的尺寸。

在这里插入图片描述
在这里插入图片描述

二、代码演示

1.这里用到的是OpenCV图像基本运算,两图相减。使用的API是subtract()。
代码是传入两张图像

void imageSubtract(Mat &image1, Mat &image2)
{
	if ((image1.rows != image2.rows) || (image1.cols != image2.cols))
	{
		if (image1.rows > image2.rows)
		{
			resize(image1, image1, image2.size(), 0, 0, INTER_LINEAR);
		}
		else if (image1.rows < image2.rows)
		{
			resize(image2, image2, image1.size(), 0, 0, INTER_LINEAR);
		}
	}

	Mat image1_gary, image2_gary;
	if (image1.channels() != 1)
	{
		cvtColor(image1, image1_gary, COLOR_BGR2GRAY);
	}
	if (image2.channels() != 1)
	{
		cvtColor(image2, image2_gary, COLOR_BGR2GRAY);
	}

	Mat frameDifference, absFrameDifferece;
	Mat previousGrayFrame = image2_gary.clone();
	//图1减图2
	subtract(image1_gary, image2_gary, frameDifference, Mat(), CV_16SC1);

	//取绝对值
	absFrameDifferece = abs(frameDifference);

	//位深的改变
	absFrameDifferece.convertTo(absFrameDifferece, CV_8UC1, 1, 0);
	imshow("absFrameDifferece", absFrameDifferece);
	Mat segmentation;
	
	//阈值处理(这一步很关键,要调好二值化的值)
	threshold(absFrameDifferece, segmentation,100, 255, THRESH_BINARY);

	//中值滤波
	medianBlur(segmentation, segmentation, 3);

	//形态学处理(开闭运算)
	//形态学处理用到的算子
	Mat morphologyKernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
	morphologyEx(segmentation, segmentation, MORPH_CLOSE, morphologyKernel, Point(-1, -1), 2, BORDER_REPLICATE);

	//显示二值化图片
	imshow("segmentation", segmentation);

	//找边界
	vector< vector<Point> > contours;
	vector<Vec4i> hierarchy;
	findContours(segmentation, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));//CV_RETR_TREE
	vector< vector<Point> > contours_poly(contours.size());

	vector<Rect> boundRect;
	boundRect.clear();

	for (int index = 0; index < contours.size(); index++)
	{
		approxPolyDP(Mat(contours[index]), contours_poly[index], 3, true);
		Rect rect = boundingRect(Mat(contours_poly[index]));
		rectangle(image2, rect, Scalar(0, 255, 0), 2);
	}
	imshow("效果图", image2);
}

2.运行效果
在这里插入图片描述

结语

1.例子很简单,但是这个方法用到移动目标追踪的上去,就是两帧差。
2.关于工程的源码,运行程序时的bug,都可以加这个群(487350510)互相讨论学习。

2013-11-21 16:43:51 Stk_OverFlow 阅读数 3025

a部分练习的是图像相减法图像的减法又称减影技术,是指对同一景物在不同时间拍摄的图像或同一景物在不同波段的图像进行相减。

其主要作用如下:

1、去除不需要的叠加性图案;

2、运动检测;

3、梯度图像。

 

这是两张在不同时刻拍摄的图像,为了充分展示出效果,我将图像中的物体移动了一下:

图    一

图    二

这两幅图像相减,并取绝对值之后的结果图像:

 图    三

可以看出,图像相减可以去除两张图像中相同的部分,找出两幅图像中不同的部分。

 

b部分对图三(即图像相减的结果图像)先进行腐蚀(Erosion)操作,再进行膨胀(Dilation)操作,实际上就是一个形态学开运算(Opening)。

图三执行形态学开运算后的结果图像:


图    四

其结果和图三比较,可以看出开运算的结果是去除了小的明亮区域,并且剩余的明亮区域被隔绝,但其大小不变。

 

c部分对图三(即图像相减的结果图像)先进行膨胀操作,再进行腐蚀操作,实际上就是一个形态学闭运算(Closing)。

图三执行形态学开运算后的结果图像:

图    五

其结果和图三比较,可以看出闭运算的结果是填充了明亮的对象内细小的黑暗空洞,连接了邻近对象,但其基本的大小不变。

 

总而言之,开运算常用于去除小的亮点,闭运算去除小的暗点。

最后,贴上代码:

#include <stdio.h>
#include <opencv\cv.h>
#include <opencv\highgui.h>
#include <opencv_libs247d.h>


int main()
{
    IplImage * src1 = cvLoadImage("frame_28.bmp", CV_LOAD_IMAGE_GRAYSCALE);
    IplImage * src2 = cvLoadImage("frame_52.bmp", CV_LOAD_IMAGE_GRAYSCALE);

    IplImage * diff12 = cvCreateImage(cvGetSize(src1), src1->depth, src1->nChannels);
    IplImage * cleandiff = cvCreateImage(cvGetSize(src1), src1->depth, src1->nChannels);
    IplImage * dirtydiff = cvCreateImage(cvGetSize(src1), src1->depth, src1->nChannels);

    cvAbsDiff(src1, src2, diff12);
    
    // Opening
    cvErode(diff12, cleandiff, NULL, 1);
    cvDilate(cleandiff, cleandiff, NULL, 1);

    // Closing
    cvDilate(diff12, dirtydiff);
    cvErode(dirtydiff, dirtydiff);

    cvShowImage("abs diff", diff12);
    cvShowImage("clean diff", cleandiff);
    cvShowImage("dirty diff", dirtydiff);

    cvSaveImage("absdiff.png", diff12);
    cvSaveImage("cleandiff.png", cleandiff);
    cvSaveImage("dirtydiff.png", dirtydiff);

    cvSaveImage("src1.png", src1);
    cvSaveImage("src2.png", src2);

    cvWaitKey(0);

    cvReleaseImage(&src1);
    cvReleaseImage(&src2);
    cvReleaseImage(&diff12);
    cvReleaseImage(&cleandiff);
    cvReleaseImage(&dirtydiff);
    cvDestroyAllWindows();

    return 0;
}

2019-12-12 10:31:19 weixin_44132302 阅读数 11

涉及:图片读取,图片保存,感兴趣区域选取,图像相减

找出下面两张图之间的八个不同

原图:
原图

代码:

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void find_difference()
{
	string path = "C:/Users/admin/Desktop/chickenspot8.jpg";
	Mat src_img = imread(path, 0);//按灰度值读取图片
	
	Rect roi1 = Rect(35, 140, 330, 240);//把原图的两幅图片选取出来
	Rect roi2 = Rect(35, 374, 330, 240);
	Mat img1 = src_img(roi1);
	Mat img2 = src_img(roi2);

	Mat result_img = abs(img2 - img1);//图像相减

	imshow("原图", src_img);//显示图片
	imshow("对比图1", img1);
	imshow("对比图2", img2);
	imshow("结果", result_img);
	waitKey();

	imwrite("C:/Users/admin/Desktop/对比图1.jpg", img1);//保存图片
	imwrite("C:/Users/admin/Desktop/对比图2.jpg", img2);
	imwrite("C:/Users/admin/Desktop/结果.jpg", result_img);

}


int main()
{
	find_difference();
}

运行结果:
对比1 对比2 结果

2015-09-13 12:36:05 linczone 阅读数 9338

[原创] python下 opencv图像减法测试

Author: chad
Mail: linczone@163.com

视频图像动态检测原理实验

实验原理,输入两幅图像s1 / s2 ,然后将两张图片相减,如果变换的像素超过一定阈值则说明图像中有运动物体。

实验1:
直接使用opencv提供的图像减法功能:

Cv2.imread默认读取的是全彩图片,为了便于处理,我们需要使用灰度图,调用如下:
cv2.imread( picpathname, 0 )使用参数0指定读取灰度图。
图像相减的时候直接s1 - s2 即可,结果如下图:
这里写图片描述
局部放大图:
这里写图片描述

隐约可以看到有变换的数字。

彩图直接相减结果如下:
这里写图片描述
局部放大图:
这里写图片描述

上面的结果非常混乱,这是为什么呢?!!

最后发现原因如下:

➜  ~  python
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> x = np.uint8(10)
>>> y = np.uint8(12)
>>> x-y
__main__:1: RuntimeWarning: overflow encountered in ubyte_scalars
254
>>> y-x
2

当结果为负值导致计算溢出,进而导致出错。

实验2:

解决办法就是自己写图像减法程序,python程序如下:
程序中增加了二值化部分,阈值小于20的统统为0,大于的为255.

#!/usr/bin/env python

import cv2
import numpy as np
ph1 = "/home/chad/011.jpg"
ph2 = "/home/chad/014.jpg"

threshod= 20 

s1 = cv2.imread(ph1,0)
s2 = cv2.imread(ph2,0)

emptyimg = np.zeros(s1.shape,np.uint8)

def pic_sub(dest,s1,s2):
    for x in range(dest.shape[0]):
        for y in range(dest.shape[1]):
            if(s2[x,y] > s1[x,y]):
                dest[x,y] = s2[x,y] - s1[x,y]
            else:
                dest[x,y] = s1[x,y] - s2[x,y]

            if(dest[x,y] < threshod):
                dest[x,y] = 0
            else:
                dest[x,y] = 255



pic_sub(emptyimg,s1,s2)

cv2.namedWindow("s1")
cv2.namedWindow("s2")
cv2.namedWindow("result")

cv2.imshow("s1",s1)
cv2.imshow("s2",s2)
cv2.imshow("result",emptyimg)

cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果如下:
这里写图片描述

标度差值图像

阅读数 1830

没有更多推荐了,返回首页