时间为友,记录点滴
集合论作为数学根基的一个大分支,在OpenCV中怎么能少了它。
首先,我们要理解一些名词:
-
:属于
如果a是集合A={a, b}的一个元素,可以记做a
A
-
:不属于
如果c不是集合A={a,b}的一个元素,可以记做c
A
-
:空集
如果集合A中什么元素都没有,可以记做A=
- U:全集
一个领域内所有可能元素的集合。一般来说,全集没有固定的符号,我们可以按照流行把U记做全集。
-
:子集
如果集合A中的元素全部都是集合B的,可以记做A
B,称A是B的子集。
-
:并集
如果集合C有且只有集合A和集合B的所有元素,可以记做C=A
B,称C是A和B的并集。
-
:交集
如果集合D有且只有集合A和集合B中共同的元素,可以记做D=A
B,称D是A和B的交集。
-
:补集
如果集合A是全集U中的一个子集,那么
就表示在全集U中除了集合A以外的其他元素的集合。
好了,回忆起这些最简单的概念就够了,比背高斯密度函数好多了。我们先写一个简单的例子。按照《数字图像处理》中的一个对比图,我们可以把一张照片做反色处理。
在图像处理中的反色,其实就是对每个像素的点做补集。这个补集什么概念呢?我们假设一张CVU8C1的图,那么一个像素的全集U={0, ...., 255},其中0代表黑色,255代表白色。那么如果一个任何一个像素的值a都应该落在全集里,我们把这个数值想象成一个有长度的线段,它的值就代表了有多白的程度,所以反过来对他做补集的物理含义就是用255-a计算出来,代表“离白”的程度,也可以想象成黑的程度。
C++
注意点:
- Mat 出来的对象,可以用Scalar来填充默认值。
- bitwise_not现有的API和255-Value得到的结果是一样的。
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
#define BONE_PIC "Fig0232(a)(partial_body_scan).tif"
using namespace std;
using namespace cv;
static bool complementSetTest(Mat imgOri);
int main()
{
Mat imgBoneOri = imread(BONE_PIC);
if (imgBoneOri.empty())
{
cout << "Cannot find this picture!" << endl;
return false;
}
imshow("boneOri", imgBoneOri);
complementSetTest(imgBoneOri);
waitKey(0);
return true;
}
static bool complementSetTest(Mat imgOri)
{
Mat imgOut(imgOri.size(), imgOri.type(), Scalar(255, 255, 255));
if (CV_8UC3 != imgOri.type())
{
cout << "Can not match this picture type!" << endl;
return false;
}
imgOut = imgOut - imgOri;
//bitwise_not(imgOri, imgOut);
imshow("imgBoneCom", imgOut);
imwrite("BoneCom.png", imgOut);
return true;
}
结果:
Python:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:lowkeyway time:7/19/2019
import sys
import cv2 as cv
import numpy as np
def main_func(argv):
imgBone = cv.imread("Fig0232(a)(partial_body_scan).tif")
cv.imshow("boneOri", imgBone)
imgOut = np.zeros(imgBone.shape, imgBone.dtype)
cv.bitwise_not(imgBone, imgOut)
cv.imshow("boneOut", imgOut)
cv.imwrite("bonBitwiseNot.png", imgOut)
cv.waitKey(0)
if __name__ == '__main__':
main_func(sys.argv)
至此,我们基本把图的操作都介绍了一遍。罗列一下:
//基本运算:
void add(InputArray src1, InputArray src2, OutputArray dst,InputArray mask=noArray(), int dtype=-1);//dst = src1 + src2
void subtract(InputArray src1, InputArray src2, OutputArray dst,InputArray mask=noArray(), int dtype=-1);//dst = src1 - src2
void multiply(InputArray src1, InputArray src2,OutputArray dst, double scale=1, int dtype=-1);//dst = scale*src1*src2
void divide(InputArray src1, InputArray src2, OutputArray dst,double scale=1, int dtype=-1);//dst = scale*src1/src2
void divide(double scale, InputArray src2,OutputArray dst, int dtype=-1);//dst = scale/src2
void scaleAdd(InputArray src1, double alpha, InputArray src2, OutputArray dst);//dst = alpha*src1 + src2
void addWeighted(InputArray src1, double alpha, InputArray src2,double beta, double gamma, OutputArray dst, int dtype=-1);
void sqrt(InputArray src, OutputArray dst);//计算每个矩阵元素的平方根
void pow(InputArray src, double power, OutputArray dst);//src的power次幂
void exp(InputArray src, OutputArray dst);//dst = e**src(**表示指数的意思)
void log(InputArray src, OutputArray dst);//dst = log(abs(src))
//逻辑运算:
void bitwise_and(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray());//dst = src1 & src2
void bitwise_or(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray());//dst = src1 | src2
void bitwise_xor(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray());//dst = src1 ^ src2
void bitwise_not(InputArray src, OutputArray dst,InputArray mask=noArray());//dst = ~src