日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

图像差分的方法

發布時間:2024/3/24 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图像差分的方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

差分圖像的幾個方法

2017/7/25


在處理圖像的時候,特別是處理視頻流圖像的時候,往往會用到圖像差分的方法。顧名思義,圖像差分,就是把兩幅圖像的對應像素值相減,以削弱圖像的相似部分,突出顯示圖像的變化部分。例如,差分圖像往往能夠檢測出運動目標的輪廓,能夠提取出閃爍導管的軌跡等等。

?

???????? 那么,該如何對圖像進行差分呢,或者說輸入一個視頻流,如何進行差分處理呢。

???????? 懂點OpenCV的同學可能就要說了,opencv里不是有現成的函數實現差分的嗎,直接拿來用就可以了,廢話那么多作甚。沒錯,OpenCV里跟差分相關的函數有兩個,一個是cvSub()函數,一個是cvAbsDiff()函數。先來看看這兩個函數的參數。

?

void cvSub(const CvArr* src1, const CvArr* src2, CvArr* dst,const CvArr* mask=NULL);

?

兩個輸入圖像src1src2和一個輸出圖像dst具有相同的類型和大小。cvSub適用于IplImage以及cvMat兩種結構。一個簡單的例子如下:

#include <opencv2/opencv.hpp>

?

int main()

{

??? IplImage*src1 = cvLoadImage("E:\\testvideo\\test1.png");

??? IplImage*src2 = cvLoadImage("E:\\testvideo\\test2.png");

??? assert(src1);

??? IplImage*dst = cvCreateImage(cvGetSize(src1),src1->depth,src1->nChannels);

??? cvSub(src1,src2,dst);

??? cvShowImage("1",src1);

??? cvShowImage("2",src2);

??? cvShowImage("dst",dst);

??? cvWaitKey(0);

}




執行結果:


如果將代碼cvSub(src1,src2,dst);改為cvSub(src2,src1,dst);則差分結果為:


這說明,cvSub()函數是直接將兩者的像素值相減,差值小于零的歸一到零處理,而沒有取差的絕對值。同時,也說明了cvSub()不僅支持灰度圖像,也支持三通道圖像。

?

cvAbsDiff()函數計算了兩幅圖像中差的絕對值。其參數跟cvSub()函數類似,如下所示,

?

void cvAbsDiff(const CvArr* src1, const CvArr* src2, CvArr* dst );

?

所以cvAbsDiff(src2,src1,dst);和cvAbsDiff(src1,src2,dst);的執行結果一樣,如下:



但是,很多人肯定想著自己實現代碼,并進行優化,

/*圖像的差分

*要求輸入輸出圖像有相同的格式和大小

*/

void? cvSub(IplImage* src1,IplImage*src2,IplImage* dst)

{

??? IplImage*src1_gray = cvCreateImage(cvGetSize(src1),8,1);

??? IplImage*src2_gray = cvCreateImage(cvGetSize(src2),8,1);

??? cvCvtColor(src1,src1_gray,CV_RGB2GRAY);

??? cvCvtColor(src2,src2_gray,CV_RGB2GRAY);

??? CvScalarpixel;

??? for (int i = 0;i <src1->height; i++)

??????? for (int j = 0; j< src1->width; j++)

??????? {

??????????? CvScalarp1 = cvGet2D(src1_gray,i,j);

??????????? CvScalarp2 = cvGet2D(src2_gray,i,j);

??????????? pixel.val[0]= abs(p1.val[0] - p2.val[0])*120/(p1.val[0]);?//相對灰度值

??????????? cvSet2D(dst,i,j,pixel);

??????? }

??????? cvReleaseImage(&src1_gray);

??????? cvReleaseImage(&src2_gray);

??????? cvShowImage("result",dst);

}

int main()

{

?? ?IplImage*src1 = cvLoadImage("D:\\test1.png");

?? ?IplImage*src2 = cvLoadImage("D:\\test2.png");

?? ?assert(src1);

?? ?IplImage*dst = cvCreateImage(cvGetSize(src1), src1->depth, src1->nChannels);

?? ?cvSub(src1, src2, dst);

?? ?cvShowImage("1", src1);

?? ?cvShowImage("2", src2);

?? ?cvShowImage("dst", dst);

?? ?cvWaitKey(0);

}

運行效果如下:


//圖像差分
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/ml.hpp"

using namespace std;

void Image_Minus(IplImage *X, IplImage *Y, IplImage *X_Y)
{
?? ?//圖像差分函數,將圖像1中像素和圖像2中對應像素想減,要求X、Y、X_Y大小相同
?? ?int i, j, width, height, step, chanel;
?? ?unsigned char *dataX, *dataY, *dataX_Y;

?? ?width = X->width;
?? ?height = X->height;

?? ?//存入矩陣數據
?? ?dataX = (unsigned char *)X->imageData;
?? ?dataY = (unsigned char *)Y->imageData;
?? ?dataX_Y = (unsigned char *)X_Y->imageData;

?? ?//計算步長
?? ?step = X->widthStep / sizeof(char);
?? ?chanel = X->nChannels;

?? ?//一個個數據處理
?? ?for (i = 0; i<height; i++)
?? ?for (j = 0; j<width*chanel; j++)
?? ??? ?dataX_Y[i*step + j] = abs(dataX[i*step + j] - dataY[i*step + j]);
}


int main()
{
?? ?IplImage* pImgX;
?? ?IplImage* pImgY;
?? ?IplImage* pImgX_Y;
?? ?CvSize dest_size;
?? ?pImgX = cvLoadImage("D:\\test1.png", -1);
?? ?pImgY = cvLoadImage("D:\\test2.png", -1);

?? ?if (pImgX == 0 || pImgY == 0)
?? ?{
?? ??? ?printf("載入文件失敗!/n");
?? ??? ?return -1;
?? ?}
?? ?dest_size.width = pImgX->width;
?? ?dest_size.height = pImgX->height;

?? ?cout << "width == " << dest_size.width << endl;
?? ?cout << "height == " << dest_size.height << endl;

?? ?pImgX_Y = cvCreateImage(dest_size, pImgX->depth, pImgX->nChannels);

?? ?//圖像差分,最最關鍵的一步
?? ?Image_Minus(pImgX, pImgY, pImgX_Y);


?? ?//創建窗口
?? ?cvNamedWindow("Picture X:", 1);
?? ?cvNamedWindow("Picture Y:", 1);
?? ?cvNamedWindow("Picture X-Y:", 1);
?? ?//顯示圖像
?? ?cvShowImage("Picture X:", pImgX);
?? ?cvShowImage("Picture Y:", pImgY);
?? ?cvShowImage("Picture X-Y:", pImgX_Y);
?? ?cvWaitKey(0);
?? ?//銷毀窗口
?? ?cvDestroyWindow("Picture X:");
?? ?cvDestroyWindow("Picture Y:");
?? ?cvDestroyWindow("Picture X-Y:");
?? ?//釋放圖像
?? ?cvReleaseImage(&pImgX);
?? ?cvReleaseImage(&pImgY);
?? ?cvReleaseImage(&pImgX_Y);
?? ?return 0;
}

效果如下圖:


總結

以上是生活随笔為你收集整理的图像差分的方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。