下面是一个简单的例子,可以使用OpenCV库来数一张图片中的小球数量:
import cv2
# 读取图片
img = cv2.imread("balls.jpg")
# 将图片转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 使用阈值分割法,得到二值图
thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)[1]
# 寻找图像中的轮廓
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
# 显示图像中的轮廓数量
print("图像中的轮廓数量:{}".format(len(cnts)))
ImageJ可以。ImageJ是一款常用的生物图像处理软件,通过软件打开要计数的图片,将彩色图片转换为8-bit格式,调整阈值,将所有胞核变为纯黑,背景变为纯白。拖动滑块时,红色显示即为我们所要计数的细胞,可自由调整,以排除较小的细胞杂质。最后到了分析计数步骤,点击“Analyze Particles”后,可出现d窗,d窗里,需要设置“Size”范围,以排除杂质。一般我们最小Size值设置为50-100范围内均可,每次实验计数时最好保持最小Size值一致,点击“OK”,即可出现细胞数量。
用ImageJ的来为图片上的粒子计数,这里的粒子可以是细胞、克隆、孢子、菌落、病斑等。
可以参考下面的程序,其中bitCount!=8 &&bitCount!=24指的就是8位与24位//BMP与IplImage相互转换
///////////////////////////////头文件bmp2ipl.h
//bmp2ipl.h
#ifndef BMP2IPL_H
#define BMP2IPL_H
class BMP {
public:
BMP():bmpData(NULL) {
memset(&biHeader, 0, sizeof(biHeader))
}
BMP(const BMP &img)
BMP(const IplImage &img)
BMP(int width, int height, int bitCount)
~BMP(){ delete [] bmpData}
bool CreateImage(const BITMAPINFOHEADER &biHeader)
//Export
IplImage * BMP2Ipl()
//void Show(HWND hWnd, int nID)
//void Show(CDC *pDC, CRect &rect)
//void Show(HWND hWnd)
void ReSize(int newW, int newH)
private:
void CopyData(char *dest, const char *src, int dataByteSize,
bool isConvert, int height)
// isConvert=true 进行顶左和底左之间的转换(顶左到底左或底左到顶左),否则不转换
// biSizeImage may be set to zero for BI_RGB bitmaps, so calculate it.
int ImgSize() {
return ( biHeader.biHeight * ((biHeader.biWidth * biHeader.biBitCount / 8 + 3) &(-4)))
}
public:
void Clear()
BITMAPINFOHEADER biHeader
unsigned char * bmpData
}
#endif
/////////////////////////////////////////////////////////////////////实现文件bmp2ipl.cpp
#include "bmp2ipl.h"
/**************************************************************************************************
* *
* NOTE: *
* Only use the "8 bit, 1 or 3 channels" image, the BitMap use LowerLeft (底左), *
* the IplImage use TopLeft (顶左) *
* IplImage: *
* nChannels = 1 or 3 number of channels *
* depth = IPL_DEPTH_8U pixel depth (8 bit), IPL_DEPTH_8U=8 *
* dataOrder = 0 交叉存取颜色通道 *
* origin = IPL_ORIGIN_TL 图像数据保存形式,IPL_ORIGIN_BL底左结构, IPL_ORIGIN_TL顶左结构 *
* align = 4 行数据对齐方式,保证下一行数据从整4字节位置开始 *
* width *
* height *
* widthStep 图像数据行大小,单位字节 *
* imageSize 图像数据大小(=height*widthStep),单位字节 *
* imageData 指向图像数据区,char * *
* BITMAPINFOHEADER: *
* biSize Specifies the number of bytes required by the structure *
* biWidth *
* biHeight(>0) biHeight>0底左结构;biHeight<0顶左结构 *
* biPlanes = 1 Specifies the number of planes for the target device. This value *
* must be set to 1. *
* biBitCount =8 or 24 bits-per-pixel,8-(pixelDepth=8,channels=1), *
* 24-(pixelDepth=8,channels=3) *
* biCompression = BI_RGB An uncompressed format *
* biSizeImage Specifies the size, in bytes, of the image.This may be set to zero *
* for BI_RGB bitmaps. *
* biXPelsPerMeter = 0 *
* biYPelsPerMeter = 0 *
* biClrUsed = 0 *
* biClrImportant = 0 *
* *
***************************************************************************************************/
BMP::BMP(const BMP &img)
{
if(!IsSupport(img)) {
BMP()
return
}
//biHeader = img.biHeader
PBITMAPINFOHEADER pBmpH = (PBITMAPINFOHEADER)&img.biHeader
memcpy(&biHeader, pBmpH, sizeof(BITMAPINFOHEADER))
biHeader.biSizeImage = ImgSize()
bool isLowerLeft = biHeader.biHeight>0
//int rowSize=0
if(!isLowerLeft) biHeader.biHeight=-biHeader.biHeight
if(bmpData!=NULL) delete[] bmpData
bmpData = new unsigned char [biHeader.biSizeImage]
//memcpy(bmpData, img.bmpData, img.biHeader.biSizeImage)
CopyData((char *)bmpData, (char*)img.bmpData, biHeader.biSizeImage,
!isLowerLeft, biHeader.biHeight)
}
BMP::BMP(const IplImage &img) {
if(!IsSupport(img)) {
BMP()
return
}
bool isTopLeft = (img.origin == IPL_ORIGIN_TL)
biHeader.biSize = sizeof(BITMAPINFOHEADER)
biHeader.biWidth = img.width
biHeader.biHeight = img.height
biHeader.biPlanes = 1
biHeader.biBitCount = img.depth * img.nChannels
biHeader.biCompression = BI_RGB
biHeader.biSizeImage = img.imageSize
biHeader.biXPelsPerMeter = 0
biHeader.biYPelsPerMeter = 0
biHeader.biClrUsed = 0
biHeader.biClrImportant = 0
if(bmpData!=NULL) delete[] bmpData
bmpData = new unsigned char [img.imageSize]
//memcpy(bmpData, img.ImageData, img.imageSize)
CopyData((char*)bmpData, (char*)img.imageData, img.imageSize,
isTopLeft, img.height)
/*int i,j
CvScalar s
for(i=0i<img.widthi++)
for(j=0j<img.heightj++){
s=cvGet2D(&img,i,j)
}
*/
}
BMP::BMP(int width, int height, int bitCount) {
if(bitCount!=8 &&bitCount!=24) return
biHeader.biSize = sizeof(BITMAPINFOHEADER)
biHeader.biWidth = width
biHeader.biHeight = height
biHeader.biPlanes = 1
biHeader.biBitCount = bitCount
biHeader.biCompression = BI_RGB
biHeader.biSizeImage = ImgSize()
biHeader.biXPelsPerMeter = 0
biHeader.biYPelsPerMeter = 0
biHeader.biClrUsed = 0
biHeader.biClrImportant = 0
if(bmpData!=NULL) delete[] bmpData
bmpData = new unsigned char [biHeader.biSizeImage]
Clear()
}
// dest: the destination image
// dataByteSize: the Source image
// height: source image height
void BMP::CopyData(char *dest, const char *src, int dataByteSize,
bool isConvert, int height) {
char * p = dest
if(!isConvert) {
memcpy(dest, src, dataByteSize)
return
}
if(height<=0) return
//int height = dataByteSize/rowByteSize
int rowByteSize = dataByteSize / height
src = src + dataByteSize - rowByteSize
for(int i=0i<heighti++) {
memcpy(dest, src, rowByteSize)
dest += rowByteSize
src -= rowByteSize
}
}
IplImage * BMP::BMP2Ipl() {
if(!IsSupport(*this)) return NULL
IplImage *iplImg
int height
bool isLowerLeft = biHeader.biHeight>0
height = (biHeader.biHeight>0) ? biHeader.biHeight : -biHeader.biHeight
iplImg = cvCreateImage( cvSize(biHeader.biWidth, height), IPL_DEPTH_8U, biHeader.biBitCount / 8)
//iplImg = cvCreateImageHeader( cvSize(biHeader.biWidth, height), IPL_DEPTH_8U, biHeader.biBitCount / 8)
//cvSetData(iplImg,(char*)bmpData,biHeader.biSizeImage/height)
CopyData( iplImg->imageData, (char*)bmpData, biHeader.biSizeImage,
isLowerLeft, height)
/*int i,j
CvScalar s
int channels=biHeader.biBitCount / 8
int step=(biHeader.biWidth*channels+3) &-4
int loc=0
for(i=0i<iplImg->heighti++){
for(j=0j<iplImg->widthj++){
loc=i*step + j*channels
s.val[0]=bmpData[loc]
if(channels==3){
s.val[1]=bmpData[loc+1]
s.val[2]=bmpData[loc+2]
}
cvSet2D(iplImg,i,j,s)
}
}*/
return iplImg
}
void BMP::Clear() {
if(bmpData == NULL) return
memset(bmpData, 0, ImgSize())
}
void BMP::ReSize(int newW, int newH) {
biHeader.biWidth = newW
biHeader.biHeight = newH
biHeader.biSizeImage = ImgSize()
if(bmpData!=NULL) delete[] bmpData
bmpData = new unsigned char [biHeader.biSizeImage]
Clear()
}
bool BMP::CreateImage(const BITMAPINFOHEADER &bih) {
memset(&biHeader,0,sizeof(BITMAPINFOHEADER))
delete[] bmpData
bmpData = NULL
memcpy(&biHeader, &bih, sizeof(BITMAPINFOHEADER))
biHeader.biSizeImage = ImgSize()
bmpData = new unsigned char [ biHeader.biSizeImage ]
if(bmpData == NULL) return false
else{
Clear()
return true
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)