大家好,又见面了,我是你们的朋友全栈君。
最近遇到一个很奇怪的问题,一直没有解决,就是在A图像中设置一个ROI,将其clone给B,然后对B进行二值化,输入
为B,输出为C,这时二值化完后的图像C跟ROI区域的图像区域不同。通过查看发现罪魁祸首是widthStep变了。
无意中解决了这个问题,做法如下:
方法1:就是在A图像中设置一个ROI,将其clone给B,新建一个C,大小、位数和通道数同B,将B clone给C,然后对C进行
InToIn的二值化操作,这个问题就解决了。
方法2:只拿二值化的阈值,在otsu函数里面不进行二值化操作,然后调用cvThreshold函数进行二值化。
现象1:异常
源代码:
// Otsu.cpp : Defines the entry point for the console application.
//
#include “stdafx.h”
#include <iostream.h>
#include <math.h>
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <windows.h>
int height;int width;
int otsu(IplImage* A, IplImage* B)
{
long N = height * width;
int h[256];
double p[256],u[256],w[256];
for(int i = 0; i < 256; i++)
{
h[i] = 0;
p[i] = 0;
u[i] = 0;
w[i] = 0;
}
for(i = 0; i < height; i++)
for(int j = 0; j < width; j++)
for(int k = 0; k < 256; k++)
{
if(((uchar*)(A->imageData + A->widthStep*i))[j] == k)
h[k]++;
}
for(i = 0; i < 256; i++)
p[i] = h[i] / double(N);
int T = 0;
double uT,thegma2fang;
double thegma2fang_max = -10000;
for(int k = 0; k < 256; k++)
{
uT = 0;
for(i = 0; i <= k; i++)
{
u[k] += i*p[i];
w[k] += p[i];
}
for(i = 0; i < 256; i++)
uT += i*p[i];
thegma2fang = (uT*w[k] – u[k])*(uT*w[k] – u[k]) / (w[k]*(1-w[k]));
if(thegma2fang > thegma2fang_max)
{
thegma2fang_max = thegma2fang;
T = k;
}
}
for(i = 0; i < height; i++) //根据最佳阈值,对原图像进行处理二值化处理
for(int j = 0; j < width; j++)
if(((uchar*)(A->imageData + A->widthStep*i))[j] > T)
((uchar*)(B->imageData + B->widthStep*i))[j] = 255;
else
((uchar*)(B->imageData + B->widthStep*i))[j] = 0;
return T;
}
int main(int argc, char** argv)
{
const char* filename = argc >= 2 ?argv[1] : “lena.jpg”;
IplImage* source = cvLoadImage( filename, 0 );
int Th;
height = source->height;
width = source->width;
CvRect rect;
rect.x=50;
rect.y=30;
rect.width=height/2;
rect.height=width/2;
IplImage *roi = cvCreateImage(cvSize(rect.width,rect.height),IPL_DEPTH_8U,1);
IplImage *bw = cvCreateImage(cvSize(rect.width,rect.height),IPL_DEPTH_8U,1);
cvSetImageROI(source,rect);
roi=cvCloneImage(source);
cvResetImageROI(source);
Th = otsu(roi,bw);
printf(“Th=%d\n”,Th);
cvNamedWindow( “Resource”, 1 );
cvShowImage( “Resource”, source );
cvNamedWindow( “Result”, 1 );
cvShowImage( “Result”, roi);
cvNamedWindow( “BW”, 1 );
cvShowImage( “BW”, bw);
cvWaitKey(0);
return 0;
}
现象2:正常
// Otsu.cpp : Defines the entry point for the console application.
//
#include “stdafx.h”
#include <iostream.h>
#include <math.h>
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <windows.h>
int height;int width;
int otsu(IplImage* A, IplImage* B)
{
long N = height * width;
int h[256];
double p[256],u[256],w[256];
for(int i = 0; i < 256; i++)
{
h[i] = 0;
p[i] = 0;
u[i] = 0;
w[i] = 0;
}
for(i = 0; i < height; i++)
for(int j = 0; j < width; j++)
for(int k = 0; k < 256; k++)
{
if(((uchar*)(A->imageData + A->widthStep*i))[j] == k)
h[k]++;
}
for(i = 0; i < 256; i++)
p[i] = h[i] / double(N);
int T = 0;
double uT,thegma2fang;
double thegma2fang_max = -10000;
for(int k = 0; k < 256; k++)
{
uT = 0;
for(i = 0; i <= k; i++)
{
u[k] += i*p[i];
w[k] += p[i];
}
for(i = 0; i < 256; i++)
uT += i*p[i];
thegma2fang = (uT*w[k] – u[k])*(uT*w[k] – u[k]) / (w[k]*(1-w[k]));
if(thegma2fang > thegma2fang_max)
{
thegma2fang_max = thegma2fang;
T = k;
}
}
return T;
}
int main(int argc, char** argv)
{
const char* filename = argc >= 2 ?argv[1] : “lena.jpg”;
IplImage* source = cvLoadImage( filename, 0 );
int Th;
height = source->height;
width = source->width;
CvRect rect;
rect.x=0;
rect.y=0;
rect.width=height/2;
rect.height=width/2;
IplImage *roi = cvCreateImage(cvSize(rect.width,rect.height),IPL_DEPTH_8U,1);
IplImage *bw = cvCreateImage(cvSize(rect.width,rect.height),IPL_DEPTH_8U,1);
cvSetImageROI(source,rect);
roi=cvCloneImage(source);
cvResetImageROI(source);
bw = cvCloneImage(roi);
Th = otsu(bw,bw);
cvThreshold(roi,bw,Th,255,CV_THRESH_BINARY);
printf(“roi->widthStep=%d,bw->widthStep=%d\n”,roi->widthStep,bw->widthStep);
printf(“Th=%d\n”,Th);
cvNamedWindow( “Resource”, 1 );
cvShowImage( “Resource”, source );
cvNamedWindow( “Result”, 1 );
cvShowImage( “Result”, roi);
cvNamedWindow( “BW”, 1 );
cvShowImage( “BW”, bw);
cvWaitKey(0);
return 0;
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/132961.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...