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

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;
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值