FT(IG)显著+分割+Surf识别笔记(一)

来源:互联网 发布:如何复制知乎的文字 编辑:程序博客网 时间:2024/05/08 16:41

FT(IG)显著+分割+Surf识别笔记

  • FT代码注释
  • Mean Shift分割代码“
  • Surf部分`

代码块

//FT显著#include "Saliency.h"#include "cmath"//这只是显著部分,要自己写个main函数,读取图像,还要转成灰度图,太累了不复制了> void Saliency::RGB2LAB(    const vector<unsigned int>&             ubuff,    vector<double>&                 lvec,    vector<double>&                 avec,    vector<double>&                 bvec){//这部分是求RGB转到LAB的过程,要经过转XYZ的过程    int sz = int(ubuff.size());    lvec.resize(sz);    avec.resize(sz);    bvec.resize(sz);    for( int j = 0; j < sz; j++ )    {        int r = (ubuff[j] >> 16) & 0xFF;        int g = (ubuff[j] >>  8) & 0xFF;        int b = (ubuff[j]      ) & 0xFF;        double xval = 0.412453 * r + 0.357580 * g + 0.180423 * b;        double yval = 0.212671 * r + 0.715160 * g + 0.072169 * b;        double zVal = 0.019334 * r + 0.119193 * g + 0.950227 * b;        xval /= (255.0 * 0.950456);        yval /=  255.0;        zVal /= (255.0 * 1.088754);        double fX, fY, fZ;        double lval, aval, bval;        if (yval > 0.008856)        {            fY = pow(yval, 1.0 / 3.0);            lval = 116.0 * fY - 16.0;        }        else        {            fY = 7.787 * yval + 16.0 / 116.0;            lval = 903.3 * yval;        }        if (xval > 0.008856)            fX = pow(xval, 1.0 / 3.0);        else            fX = 7.787 * xval + 16.0 / 116.0;        if (zVal > 0.008856)            fZ = pow(zVal, 1.0 / 3.0);        else            fZ = 7.787 * zVal + 16.0 / 116.0;        aval = 500.0 * (fX - fY)+128.0;        bval = 200.0 * (fY - fZ)+128.0;        lvec[j] = lval;        avec[j] = aval;        bvec[j] = bval;    }}/// 高斯平滑void Saliency::GaussianSmooth(    const vector<double>&           inputImg,    const int&                      width,    const int&                      height,    const vector<double>&           kernel,    vector<double>&                 smoothImg){    int center = int(kernel.size())/2;    int sz = width*height;    smoothImg.clear();    smoothImg.resize(sz);    vector<double> tempim(sz);    int rows = height;    int cols = width;   // Blur in the x direction.    {int index(0);    for( int r = 0; r < rows; r++ )    {        for( int c = 0; c < cols; c++ )        {            double kernelsum(0);            double sum(0);            for( int cc = (-center); cc <= center; cc++ )            {                if(((c+cc) >= 0) && ((c+cc) < cols))                {                    sum += inputImg[r*cols+(c+cc)] * kernel[center+cc];                    kernelsum += kernel[center+cc];                }            }            tempim[index] = sum/kernelsum;            index++;        }    }}    // Blur in the y direction.    {int index = 0;    for( int r = 0; r < rows; r++ )    {        for( int c = 0; c < cols; c++ )        {            double kernelsum(0);            double sum(0);            for( int rr = (-center); rr <= center; rr++ )            {                if(((r+rr) >= 0) && ((r+rr) < rows))                {                   sum += tempim[(r+rr)*cols+c] * kernel[center+rr];                   kernelsum += kernel[center+rr];                }            }            smoothImg[index] = sum/kernelsum;            index++;        }    }}}/// GetSaliencyMap////// Outputs a saliency map with a value assigned per pixel. The values are/// normalized in the interval [0,255] if normflag is set true (default value).void Saliency::GetSaliencyMap(    const vector<unsigned int>&     inputimg,    const int&                      width,    const int&                      height,    vector<double>&                 salmap,    const bool&                     normflag) {    int sz = width*height;    salmap.clear();    salmap.resize(sz);    vector<double> lvec(0), avec(0), bvec(0);    RGB2LAB(inputimg, lvec, avec, bvec);    // Obtain Lab average values    double avgl(0), avga(0), avgb(0);    {for( int i = 0; i < sz; i++ )    {        avgl += lvec[i];        avga += avec[i];        avgb += bvec[i];    }}    avgl /= sz;    avga /= sz;    avgb /= sz;    vector<double> slvec(0), savec(0), sbvec(0);    // The kernel can be [1 2 1] or [1 4 6 4 1] as needed.    // The code below show usage of [1 2 1] kernel.    vector<double> kernel(0);    //高斯滤波的核是[1,2,1]    kernel.push_back(1.0);    kernel.push_back(2.0);    kernel.push_back(1.0);    GaussianSmooth(lvec, width, height, kernel, slvec);  //高斯平滑    GaussianSmooth(avec, width, height, kernel, savec);     GaussianSmooth(bvec, width, height, kernel, sbvec);    {for( int i = 0; i < sz; i++ )  //得到的结果高斯平滑减去原始图像的均值,如果有低频信号通过图像平滑最后减去均值就没有响应了,相反高频部分,通过平滑残留了高频响应减去了均值还是有响应,这部分我们认为是显著区域,最后返回结果    {        salmap[i] = (slvec[i]-avgl)*(slvec[i]-avgl) +                    (savec[i]-avga)*(savec[i]-avga) +                    (sbvec[i]-avgb)*(sbvec[i]-avgb);    }}//以上就是FT求图像显著图的主要代码    if( true == normflag )//这是归一化,就是每个图像像素值都缩小为[0-1]的函数。函数为Normalize    {        vector<double> normalized(0);        Normalize(salmap, width, height, normalized);        swap(salmap, normalized);    }}

//分割代码

#include "stdafx.h"  //stdafx.h要自己建一个这样的库// meanshift_segmentation.cpp : 定义控制台应用程序的入口点。  //  #include"opencv2/core/core.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp"  #include "iostream"  #pragma comment(lib,"opencv_highgui2413d.lib")  #pragma comment(lib,"opencv_core2413d.lib")  #pragma comment(lib,"opencv_imgproc2413d.lib")  using namespace cv;using namespace std;Mat src, dst;int spatialRad, colorRad, maxPryLevel;int main(int argc, uchar* argv[]){    int maxPyrLevel = 3;  //金字塔层数      Mat res;    double duration = static_cast<double>(getTickCount());    Mat img = imread("E:/Codes/CprimerPlus/chapter13/分割/31.jpg"); //读图路径    //路径要加引号,一般程序出错最有可能是路径问题,有绝对路径和相对路径之分,绝对路径:/    //相对路径:可直接引用程序下的图片    int spatialRad = 4; //值越大时间会越长    int colorRad = 30; //值越大图像会分割的区域数越小    pyrMeanShiftFiltering(img, res, spatialRad, colorRad, maxPyrLevel);     imshow("res", res);    RNG rng = theRNG();    Mat mask(res.rows + 2, res.cols + 2, CV_8UC1, Scalar::all(0));  //掩模      for (int y = 0; y < res.rows; y++)    {        for (int x = 0; x < res.cols; x++)        {            if (mask.at<uchar>(y + 1, x + 1) == 0)  //非0处即为1,表示已经经过填充,不再处理              {                //Scalar newVal(rng(256), rng(256), rng(256));                //floodFill(res, mask, Point(x, y), newVal, 0, Scalar::all(5), Scalar::all(5)); //执行漫水填充              }        }    }    imshow("meanShift图像分割", res);    imwrite("result.jpg", res);    duration = ((double)getTickCount() - duration) / getTickFrequency();    cout << "运行时间" << duration << "秒" << endl;    waitKey();    return 0;    }
Surf部分没什么好写的,基本是OPENCV3书上原装程序,要说所有程序完全是我自己写的只有得到分割后将它扣出来,其他都是主程序,自己修修小数据
#include "stdafx.h"  #include "opencv2/core/core.hpp"#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include "opencv2/opencv.hpp"#include "iostream"using namespace cv;using namespace std;int main(int argc, char** argv){    Mat  binary;    Mat result = imread("2.jpg", 0);//这里0表示读取图像并转为灰度图即[0-255]    Mat tongji;    threshold(result, binary, 50, 255, CV_THRESH_BINARY);//阀值化,固定阀值吧,不是自适应的。    //里面的参数分别代表;输入图像;输出图像;最低阀值,往上为1,下为0;这个图像里像素值的最大///值;二值化的表示,也有其他表示方法    Mat element = getStructuringElement(MORPH_RECT, Size(50, 50));//膨胀操作的一个自定义核    Mat out;    double maxArea = 0;    vector<cv::Point> maxContour;    dilate(binary, out, element);//膨胀。一般写前面三个参数,后面有默认的    vector<vector<cv::Point>> contours;//vector是结构体或者容器    findContours(out, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//寻找轮廓    //里面参数:输入;输出;检测轮廓类别,这个是检测最外围轮廓(还有所有轮廓并放list中,提取所有轮廓//并组织为双层结构,最后一个是提取轮廓建立网状结构);获取轮廓的每个像素。    for (int i = 0; i < contours.size(); i++)    {        double area = contourArea(contours[i]);//轮廓面积        if (area > maxArea)        {            maxArea = area;            maxContour = contours[i];        }    }    Rect maxRect = boundingRect(maxContour);//求最大轮廓面积,并返回轮廓的最大矩形    Mat original = imread("1.jpg");//原图    Mat gray = result;    Mat hole(gray.size(), CV_8U, Scalar(0));//建立模版方便抠图所用的转换,与原图大小一样    rectangle(hole, Rect(maxRect.x, maxRect.y, maxRect.width, maxRect.height), Scalar(255, 255, 255), -1, 1, 0);//刚刚矩形的位置,在模版相同的矩形位置变白色    double a = maxRect.x;    double b = maxRect.y;    double c = maxRect.width;    double d = maxRect.height;    printf("左上点x:%f\n", a);    printf("左上点y:%f\n", b);    printf("宽:%f\n", c);    printf("高:%f\n", d);//显示矩形的位置数据    namedWindow("My hole");    imshow("My hole", hole);    Mat crop(original.rows, original.cols, CV_8UC3);    original.copyTo(crop, hole);//将原图像拷贝进遮罩图层      namedWindow("My warpPerspective");    imshow("My warpPerspective", crop);    imwrite("result.jpg", crop);    imshow("image", result);    waitKey();    return 0;    }
原创粉丝点击