目前在计算间视觉中,图像分类是一个很重要的分支,有时候分类效果不好的原因是因为我们的目标框内背景像素过多导致,再此小编写了个小demo,可以把目标物分割成多张图像,每张图像目标像素点占比2/3衣上,并且把这些图片排序保存在本地。此demo在win10 64位+VS2013+opencv2013可直接使用,还附带matlab版本的,在2016b可以直接使用。
#include<opencv2/opencv.hpp>
#include<string>
#include<iostream>
#include <stdlib.h>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
//string filename;
//cout<<"please input the image file path:"<<endl;
//cin>>filename;
//Mat img = imread("11.png", 0);//声明Mat变量,并读取图片,imread中需要传入图片的绝对路径
Mat img = imread("C:\\Users\\**\\Desktop\\xiawei\\qing_mask.png",0);
unsigned char imgmat[512][1024];
for (size_t nrow = 0; nrow < img.rows; nrow++)
{
for (size_t ncol = 0; ncol < img.cols; ncol++)
{
imgmat[nrow][ncol] = img.at<unsigned char>(nrow, ncol);
}
}
typedef Point_<int> point2i;
vector<Point2i> points;
point2i point;
for (size_t i = 0; i < img.rows; i++)
{
for (size_t j = 0; j < img.cols; j++)
{
if (imgmat[i][j]>250)
{
point.x = i;
point.y = j;
points.push_back(point);
}
}
}
Mat img1 = imread("C:\\Users\\**\\Desktop\\xiawei\\qing.png");
random_shuffle(points.begin(), points.end());
for (int i = 0; i < 40; i++)
{
string Img_Name = "C:\\Users\\**\\Desktop\\xiawei\\" + to_string(i) + ".png";
int x = points.at(i).x-30;
int y = points.at(i).y-30;
int count255 = 0;
int count0 = 0;
for (int row = x; row < (x+60); row++)
{
for (int col = y; col < (y + 60); col++)
{
if (imgmat[row][col]>250)
{
count255++;
}
else{
count0++;
}
}
}
if (count255 >= count0)
{
Rect rect(y, x, 60, 60);
Mat ROI = img1(rect);
imwrite(Img_Name, ROI);
//cout << Img_Name << "已保存" << endl;
}
}
}
上面提到的两张图象一张是原图,一张是原图对应的目标物灰度图,路径改成自己的就行。下面是matlab 版本的。
clear;clc;
A=imread('qing_mask.png');
A=rgb2gray(A);
% bw=graythresh(A);
% newA=im2bw(A,bw);
[m,n]=find(A>=250);
% [m,n]=find(newA==1);
zuobiao=[m,n];
s=randi(size(zuobiao,1));
pt=zuobiao(s,:);
pt=pt-30;
pt(:,[1 2])=pt(:,[2,1]);
data = imread('qing.png');
% [m, n, z] = size(data);
% pt = [185, 273];
wSize = [60,60];
des = drawRect(data,pt,wSize,2 );
subplot(1,3,1)
imshow(data)
subplot(1,3,2)
imshow(des)
pic_1 = imcrop(data,[pt,wSize]);
subplot(1,3,3)
imshow(pic_1)
里面用到得函数如下:
function [ dest ] = drawRect( src, pt, wSize, lineSize, color )
%简介:
% %将图像画上有颜色的框图,如果输入是灰度图,先转换为彩色图像,再画框图
% 图像矩阵
% 行向量方向 是 y
% 列向量方向 是 x
%----------------------------------------------------------------------
%输入:
% src: 原始图像,可以为灰度图,可为彩色图
% pt: 左上角坐标 [x1, y1]
% wSize: 框的大小 [wx, wy]
% lineSize: 线的宽度
% color: 线的颜色 [r, g, b]
%----------------------------------------------------------------------
%输出:
% dest: 画好了的图像
%----------------------------------------------------------------------
%flag=1: 有缺口的框
%flag=2: 无缺口的框
flag = 1;
%判断输入参数个数
if nargin < 5
color = [255 255 0];
end
if nargin < 4
lineSize = 1;
end
if nargin < 3
disp('输入参数不够 !!!');
return;
end
%判断框的边界问题
[yA, xA, z] = size(src);
x1 = pt(1);
y1 = pt(2);
wx = wSize(1);
wy = wSize(2);
if x1>xA || ...
y1>yA||...
(x1+wx)>xA||...
(y1+wy)>yA
disp('画的框将超过图像 !!!');
return;
end
%如果是单通道的灰度图,转成3通道的图像
if 1==z
dest(:, : ,1) = src;
dest(:, : ,2) = src;
dest(:, : ,3) = src;
else
dest = src;
end
%开始画框图
for c = 1 : 3 %3个通道,r,g,b分别画
for dl = 1 : lineSize %线的宽度,线条是向外面扩展的
d = dl - 1;
if 1==flag %有缺口的框
dest( y1-d , x1:(x1+wx) , c ) = color(c); %上方线条
dest( y1+wy+d , x1:(x1+wx) , c ) = color(c); %下方线条
dest( y1:(y1+wy) , x1-d , c ) = color(c); %左方线条
dest( y1:(y1+wy) , x1+wx+d , c ) = color(c); %左方线条
elseif 2==flag %无缺口的框
dest( y1-d , (x1-d):(x1+wx+d) , c ) = color(c); %上方线条
dest( y1+wy+d , (x1-d):(x1+wx+d) , c ) = color(c); %下方线条
dest( (y1-d):(y1+wy+d) , x1-d , c ) = color(c); %左方线条
dest( (y1-d):(y1+wy+d) , x1+wx+d , c ) = color(c); %左方线条
end
end
end %主循环尾
end %函数尾
分割效果如下: